Map, Filter, Reduce

Array methods avanzati per programmazione funzionale moderna

🎯 Programmazione Funzionale con Array

I metodi map, filter e reduce sono i pilastri
della programmazione funzionale in JavaScript. Permettono di trasformare, filtrare e aggregare
dati in modo elegante e dichiarativo.

💡 Perché Sono Importanti?

  • Leggibilità → Codice più chiaro e espressivo
  • Immutabilità → Non modificano l’array originale
  • Composizione → Possono essere concatenati
  • Standard moderno → Usati in React, Vue, Angular…
🎯 In Questa Lezione

  • map() – Trasforma ogni elemento
  • filter() – Filtra elementi per condizione
  • reduce() – Aggrega array in singolo valore
  • find(), findIndex(), some(), every() – Metodi utility
  • Chaining – Concatenare metodi
  • Best Practices – Quando usare quale metodo

🔄 map() – Trasforma Array

map() crea un nuovo array applicando una funzione a ogni elemento.
L’array risultante ha la stessa lunghezza dell’originale.

1
Sintassi e Uso Base

map() Base
// Sintassi: array.map(callback(elemento, indice, array))

const numeri = [1, 2, 3, 4, 5];

// Con for classico (VECCHIO MODO ❌)
let doppi = [];
for (let i = 0; i < numeri.length; i++) {
    doppi.push(numeri[i] * 2);
}
console.log(doppi);  // [2, 4, 6, 8, 10]

// ✨ Con map (MODERNO ✅)
const doppiMap = numeri.map(function(numero) {
    return numero * 2;
});
console.log(doppiMap);  // [2, 4, 6, 8, 10]

// ✨ Con arrow function (CONSIGLIATO 🌟)
const doppiArrow = numeri.map(n => n * 2);
console.log(doppiArrow);  // [2, 4, 6, 8, 10]

// Array originale NON modificato
console.log(numeri);  // [1, 2, 3, 4, 5]

2
Esempi Pratici map()

map() Esempi
// Estrai proprietà da array di oggetti
const utenti = [
    {id: 1, nome: "Mario", età: 30},
    {id: 2, nome: "Anna", età: 25},
    {id: 3, nome: "Luca", età: 35}
];

const nomi = utenti.map(utente => utente.nome);
console.log(nomi);  // ["Mario", "Anna", "Luca"]

const età = utenti.map(u => u.età);
console.log(età);  // [30, 25, 35]

// Trasforma stringhe
const frutti = ["mela", "banana", "arancia"];
const maiuscole = frutti.map(f => f.toUpperCase());
console.log(maiuscole);  // ["MELA", "BANANA", "ARANCIA"]

// Crea nuovi oggetti
const prodotti = [
    {nome: "Laptop", prezzo: 999},
    {nome: "Mouse", prezzo: 25},
    {nome: "Tastiera", prezzo: 75}
];

const conSconto = prodotti.map(p => ({
    ...p,
    prezzoOriginale: p.prezzo,
    prezzo: p.prezzo * 0.8,  // 20% sconto
    sconto: "20%"
}));

console.log(conSconto);
// [{nome: "Laptop", prezzo: 799.2, prezzoOriginale: 999, sconto: "20%"}, ...]

// Con indice
const lettere = ["a", "b", "c"];
const conIndice = lettere.map((lettera, indice) => {
    return `${indice + 1}. ${lettera.toUpperCase()}`;
});
console.log(conIndice);  // ["1. A", "2. B", "3. C"]

💡 Quando Usare map()

Usa map() quando vuoi:

  • Trasformare ogni elemento dell’array
  • Estrarre proprietà da oggetti
  • Convertire formati (°C → °F, km → miglia…)
  • Creare componenti React da dati (molto comune!)

🔍 filter() – Filtra Array

filter() crea un nuovo array contenendo solo gli elementi
che superano una condizione. La lunghezza può essere diversa dall’originale.

1
Sintassi e Uso Base

filter() Base
// Sintassi: array.filter(callback(elemento, indice, array))

const numeri = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

// Con for classico (VECCHIO MODO ❌)
let pari = [];
for (let i = 0; i < numeri.length; i++) {
    if (numeri[i] % 2 === 0) {
        pari.push(numeri[i]);
    }
}
console.log(pari);  // [2, 4, 6, 8, 10]

// ✨ Con filter (MODERNO ✅)
const pariFilter = numeri.filter(function(numero) {
    return numero % 2 === 0;
});
console.log(pariFilter);  // [2, 4, 6, 8, 10]

// ✨ Con arrow function (CONSIGLIATO 🌟)
const pariArrow = numeri.filter(n => n % 2 === 0);
console.log(pariArrow);  // [2, 4, 6, 8, 10]

// Filtra dispari
const dispari = numeri.filter(n => n % 2 !== 0);
console.log(dispari);  // [1, 3, 5, 7, 9]

// Maggiori di 5
const maggiori = numeri.filter(n => n > 5);
console.log(maggiori);  // [6, 7, 8, 9, 10]

2
Esempi Pratici filter()

filter() Esempi
// Filtra oggetti per proprietà
const prodotti = [
    {nome: "Laptop", prezzo: 999, disponibile: true},
    {nome: "Mouse", prezzo: 25, disponibile: true},
    {nome: "Monitor", prezzo: 300, disponibile: false},
    {nome: "Tastiera", prezzo: 75, disponibile: true}
];

// Solo prodotti disponibili
const disponibili = prodotti.filter(p => p.disponibile);
console.log(disponibili);
// [{nome: "Laptop", ...}, {nome: "Mouse", ...}, {nome: "Tastiera", ...}]

// Prodotti economici (< €100)
const economici = prodotti.filter(p => p.prezzo < 100);
console.log(economici);
// [{nome: "Mouse", ...}, {nome: "Tastiera", ...}]

// Filtra stringhe
const parole = ["ciao", "a", "mondo", "hi", "JavaScript"];
const lunghe = parole.filter(p => p.length > 3);
console.log(lunghe);  // ["ciao", "mondo", "JavaScript"]

// Rimuovi duplicati (uso avanzato)
const numeriDuplicati = [1, 2, 2, 3, 4, 4, 5];
const unici = numeriDuplicati.filter((n, indice, array) => {
    return array.indexOf(n) === indice;
});
console.log(unici);  // [1, 2, 3, 4, 5]

// Filtra per età
const persone = [
    {nome: "Mario", età: 17},
    {nome: "Anna", età: 25},
    {nome: "Luca", età: 15},
    {nome: "Sara", età: 30}
];

const maggiorenni = persone.filter(p => p.età >= 18);
console.log(maggiorenni);
// [{nome: "Anna", età: 25}, {nome: "Sara", età: 30}]

💡 Quando Usare filter()

Usa filter() quando vuoi:

  • Trovare elementi che soddisfano una condizione
  • Rimuovere elementi indesiderati
  • Creare subset di dati
  • Implementare funzionalità di ricerca/filtro

📊 reduce() – Aggrega Array

reduce() “riduce” un array a un singolo valore
applicando una funzione cumulativa. Il più potente e flessibile!

1
Sintassi e Uso Base

reduce() Base
// Sintassi: array.reduce(callback(accumulatore, elemento, indice, array), valoreIniziale)

const numeri = [1, 2, 3, 4, 5];

// Con for classico (VECCHIO MODO ❌)
let somma = 0;
for (let i = 0; i < numeri.length; i++) {
    somma += numeri[i];
}
console.log(somma);  // 15

// ✨ Con reduce (MODERNO ✅)
const sommaReduce = numeri.reduce(function(acc, num) {
    return acc + num;
}, 0);  // 0 è il valore iniziale
console.log(sommaReduce);  // 15

// ✨ Con arrow function (CONSIGLIATO 🌟)
const sommaArrow = numeri.reduce((acc, num) => acc + num, 0);
console.log(sommaArrow);  // 15

// Come funziona step-by-step:
// Passo 1: acc = 0 (valore iniziale), num = 1 → return 0 + 1 = 1
// Passo 2: acc = 1, num = 2 → return 1 + 2 = 3
// Passo 3: acc = 3, num = 3 → return 3 + 3 = 6
// Passo 4: acc = 6, num = 4 → return 6 + 4 = 10
// Passo 5: acc = 10, num = 5 → return 10 + 5 = 15
// Risultato finale: 15

2
Esempi Pratici reduce()

reduce() Esempi
const numeri = [10, 5, 8, 3, 15];

// Somma
const somma = numeri.reduce((acc, n) => acc + n, 0);
console.log(somma);  // 41

// Prodotto
const prodotto = numeri.reduce((acc, n) => acc * n, 1);
console.log(prodotto);  // 18000

// Massimo
const max = numeri.reduce((acc, n) => n > acc ? n : acc);
console.log(max);  // 15

// Minimo
const min = numeri.reduce((acc, n) => n < acc ? n : acc);
console.log(min);  // 3

// Media
const media = numeri.reduce((acc, n, i, arr) => {
    acc += n;
    if (i === arr.length - 1) {
        return acc / arr.length;
    }
    return acc;
}, 0);
console.log(media);  // 8.2

// Conta occorrenze
const frutti = ["mela", "banana", "mela", "arancia", "banana", "mela"];
const conteggio = frutti.reduce((acc, frutto) => {
    acc[frutto] = (acc[frutto] || 0) + 1;
    return acc;
}, {});
console.log(conteggio);
// {mela: 3, banana: 2, arancia: 1}

// Raggruppa per proprietà
const persone = [
    {nome: "Mario", età: 25, città: "Roma"},
    {nome: "Anna", età: 30, città: "Milano"},
    {nome: "Luca", età: 25, città: "Roma"},
    {nome: "Sara", età: 30, città: "Milano"}
];

const perCittà = persone.reduce((acc, persona) => {
    if (!acc[persona.città]) {
        acc[persona.città] = [];
    }
    acc[persona.città].push(persona);
    return acc;
}, {});

console.log(perCittà);
// {
//   Roma: [{nome: "Mario", ...}, {nome: "Luca", ...}],
//   Milano: [{nome: "Anna", ...}, {nome: "Sara", ...}]
// }

3
reduce() Avanzato

reduce() Avanzato
// Flatten array (appiattire array annidati)
const arrayAnnidato = [[1, 2], [3, 4], [5, 6]];
const flat = arrayAnnidato.reduce((acc, arr) => acc.concat(arr), []);
console.log(flat);  // [1, 2, 3, 4, 5, 6]

// Pipeline di trasformazioni
const numeri = [1, 2, 3, 4, 5];
const risultato = numeri.reduce((acc, n) => {
    return acc.concat(n * 2);  // Moltiplica per 2
}, []).filter(n => n > 5);     // Poi filtra > 5

console.log(risultato);  // [6, 8, 10]

// Componi funzioni
const funzioni = [
    x => x + 10,
    x => x * 2,
    x => x - 5
];

const composta = funzioni.reduce((acc, fn) => {
    return x => fn(acc(x));
}, x => x);

console.log(composta(5));  // ((5 + 10) * 2) - 5 = 25

// Calcola totale carrello
const carrello = [
    {prodotto: "Laptop", prezzo: 999, quantità: 1},
    {prodotto: "Mouse", prezzo: 25, quantità: 2},
    {prodotto: "Tastiera", prezzo: 75, quantità: 1}
];

const totale = carrello.reduce((acc, item) => {
    return acc + (item.prezzo * item.quantità);
}, 0);

console.log(`Totale: €${totale}`);  // Totale: €1124

⚠️ Valore Iniziale Importante!

Fornire sempre il valore iniziale per evitare comportamenti imprevisti!

const numeri = [1, 2, 3];

// ❌ Senza valore iniziale
const somma1 = numeri.reduce((acc, n) => acc + n);
console.log(somma1);  // 6 (funziona ma...)

// ✅ Con valore iniziale (MEGLIO)
const somma2 = numeri.reduce((acc, n) => acc + n, 0);
console.log(somma2);  // 6

// ❌ Problema senza valore iniziale
const vuoto = [];
// const errore = vuoto.reduce((acc, n) => acc + n);  // TypeError!

// ✅ Con valore iniziale funziona
const sicuro = vuoto.reduce((acc, n) => acc + n, 0);
console.log(sicuro);  // 0

🔧 Altri Metodi Utili

Oltre a map, filter e reduce, ci sono altri metodi molto utili per lavorare con array.

1
find() e findIndex()

Trova il primo elemento che soddisfa la condizione.

find() e findIndex()
const utenti = [
    {id: 1, nome: "Mario", età: 30},
    {id: 2, nome: "Anna", età: 25},
    {id: 3, nome: "Luca", età: 35}
];

// find() - restituisce l'elemento
const utente = utenti.find(u => u.id === 2);
console.log(utente);
// {id: 2, nome: "Anna", età: 25}

// Se non trova, restituisce undefined
const nonEsiste = utenti.find(u => u.id === 99);
console.log(nonEsiste);  // undefined

// findIndex() - restituisce l'indice
const indice = utenti.findIndex(u => u.nome === "Luca");
console.log(indice);  // 2

// Se non trova, restituisce -1
const nonTrovato = utenti.findIndex(u => u.nome === "Paolo");
console.log(nonTrovato);  // -1

// Uso pratico: trova prodotto in carrello
const carrello = [
    {id: 1, nome: "Laptop", quantità: 1},
    {id: 2, nome: "Mouse", quantità: 2}
];

const prodotto = carrello.find(p => p.id === 2);
if (prodotto) {
    prodotto.quantità++;
    console.log(`Quantità aggiornata: ${prodotto.quantità}`);
}

2
some() e every()

Verifica se almeno uno (some) o tutti (every) soddisfano la condizione.

some() e every()
const numeri = [1, 2, 3, 4, 5];

// some() - almeno uno è vero?
const haPari = numeri.some(n => n % 2 === 0);
console.log(haPari);  // true

const haNegativi = numeri.some(n => n < 0);
console.log(haNegativi);  // false

// every() - tutti sono veri?
const tuttiPositivi = numeri.every(n => n > 0);
console.log(tuttiPositivi);  // true

const tuttiPari = numeri.every(n => n % 2 === 0);
console.log(tuttiPari);  // false

// Uso pratico: validazione form
const campi = [
    {nome: "email", valore: "test@test.com", valido: true},
    {nome: "password", valore: "abc123", valido: true},
    {nome: "telefono", valore: "", valido: false}
];

const tuttiValidi = campi.every(campo => campo.valido);
console.log(`Form valido: ${tuttiValidi}`);  // false

const almeno1Valido = campi.some(campo => campo.valido);
console.log(`Almeno 1 campo valido: ${almeno1Valido}`);  // true

// Controllo età
const persone = [
    {nome: "Mario", età: 25},
    {nome: "Anna", età: 30},
    {nome: "Luca", età: 17}
];

const tuttiMaggiorenni = persone.every(p => p.età >= 18);
console.log(`Tutti maggiorenni: ${tuttiMaggiorenni}`);  // false

3
sort() e reverse()

Ordinamento e inversione array. ⚠️ Modificano l’array originale!

sort() e reverse()
// sort() - ATTENZIONE: modifica l'originale!
const numeri = [3, 1, 4, 1, 5, 9, 2, 6];

// ❌ Sort di default (ordine lessicografico)
const malOrdinati = [1, 2, 10, 21];
malOrdinati.sort();
console.log(malOrdinati);  // [1, 10, 2, 21] (SBAGLIATO!)

// ✅ Sort numerico corretto
numeri.sort((a, b) => a - b);  // Crescente
console.log(numeri);  // [1, 1, 2, 3, 4, 5, 6, 9]

// Decrescente
numeri.sort((a, b) => b - a);
console.log(numeri);  // [9, 6, 5, 4, 3, 2, 1, 1]

// Sort stringhe
const frutti = ["banana", "mela", "arancia"];
frutti.sort();
console.log(frutti);  // ["arancia", "banana", "mela"]

// Sort oggetti
const persone = [
    {nome: "Mario", età: 30},
    {nome: "Anna", età: 25},
    {nome: "Luca", età: 35}
];

// Per età crescente
persone.sort((a, b) => a.età - b.età);
console.log(persone);
// [{nome: "Anna", età: 25}, ...]

// Per nome alfabetico
persone.sort((a, b) => a.nome.localeCompare(b.nome));

// ✅ Sort IMMUTABILE (non modifica originale)
const numeriOriginali = [3, 1, 4, 1, 5];
const ordinati = [...numeriOriginali].sort((a, b) => a - b);
console.log(numeriOriginali);  // [3, 1, 4, 1, 5] (invariato!)
console.log(ordinati);         // [1, 1, 3, 4, 5]

// reverse() - inverte array
const lettere = ["a", "b", "c"];
lettere.reverse();
console.log(lettere);  // ["c", "b", "a"]

// Immutabile
const originale = [1, 2, 3];
const invertito = [...originale].reverse();
console.log(originale);   // [1, 2, 3]
console.log(invertito);   // [3, 2, 1]

⛓️ Method Chaining

Puoi concatenare più metodi per creare pipeline di trasformazione eleganti!

Method Chaining
const prodotti = [
    {nome: "Laptop", prezzo: 999, categoria: "elettronica", disponibile: true},
    {nome: "Mouse", prezzo: 25, categoria: "elettronica", disponibile: true},
    {nome: "Sedia", prezzo: 150, categoria: "mobili", disponibile: false},
    {nome: "Monitor", prezzo: 300, categoria: "elettronica", disponibile: true},
    {nome: "Scrivania", prezzo: 200, categoria: "mobili", disponibile: true}
];

// ✨ Pipeline: filtra → mappa → ordina → riduci
const totaleElettronica = prodotti
    .filter(p => p.categoria === "elettronica")  // Solo elettronica
    .filter(p => p.disponibile)                  // Solo disponibili
    .map(p => p.prezzo)                          // Estrai prezzi
    .reduce((acc, prezzo) => acc + prezzo, 0);   // Somma

console.log(`Totale elettronica: €${totaleElettronica}`);  // €1324

// Nomi prodotti disponibili in maiuscolo, ordinati
const nomiOrdinati = prodotti
    .filter(p => p.disponibile)
    .map(p => p.nome.toUpperCase())
    .sort();

console.log(nomiOrdinati);
// ["LAPTOP", "MONITOR", "MOUSE", "SCRIVANIA"]

// Top 3 prodotti più costosi (nomi)
const top3 = prodotti
    .sort((a, b) => b.prezzo - a.prezzo)  // Ordina per prezzo desc
    .slice(0, 3)                          // Primi 3
    .map(p => p.nome);                    // Solo nomi

console.log(top3);  // ["Laptop", "Monitor", "Scrivania"]

// Media prezzi categoria elettronica
const mediaElettronica = prodotti
    .filter(p => p.categoria === "elettronica")
    .map(p => p.prezzo)
    .reduce((acc, p, i, arr) => {
        acc += p;
        return i === arr.length - 1 ? acc / arr.length : acc;
    }, 0);

console.log(`Media elettronica: €${mediaElettronica.toFixed(2)}`);

// Conta prodotti per categoria
const perCategoria = prodotti
    .reduce((acc, p) => {
        acc[p.categoria] = (acc[p.categoria] || 0) + 1;
        return acc;
    }, {});

console.log(perCategoria);  // {elettronica: 3, mobili: 2}

💡 Best Practices Chaining
  • ✅ Un metodo per riga per leggibilità
  • ✅ Filtra PRIMA di mappare (meno iterazioni)
  • ✅ Ordina DOPO aver ridotto i dati
  • ⚠️ Attenzione a performance con array grandi
  • ⚠️ Ogni metodo crea nuovo array (memoria)

📊 Confronto Metodi

Tabella Decisionale

Voglio… Metodo Restituisce Esempio
Trasformare ogni elemento map() Nuovo array (stessa lunghezza) Doppio di ogni numero
Selezionare elementi filter() Nuovo array (≤ originale) Solo numeri pari
Aggregare a valore singolo reduce() Singolo valore (qualsiasi tipo) Somma, media, oggetto
Trovare UN elemento find() Elemento o undefined Utente con id=5
Trovare posizione findIndex() Indice o -1 Indice utente “Mario”
Verificare se ALMENO UNO some() Boolean C’è almeno 1 pari?
Verificare se TUTTI every() Boolean Tutti maggiorenni?

🚀 Esempio Completo: Analytics Dashboard

Analytics Dashboard Completo
// Dataset vendite e-commerce
const vendite = [
    {id: 1, prodotto: "Laptop", categoria: "elettronica", prezzo: 999, quantità: 2, data: "2025-01-15"},
    {id: 2, prodotto: "Mouse", categoria: "elettronica", prezzo: 25, quantità: 5, data: "2025-01-15"},
    {id: 3, prodotto: "Sedia", categoria: "mobili", prezzo: 150, quantità: 1, data: "2025-01-16"},
    {id: 4, prodotto: "Monitor", categoria: "elettronica", prezzo: 300, quantità: 3, data: "2025-01-16"},
    {id: 5, prodotto: "Scrivania", categoria: "mobili", prezzo: 200, quantità: 2, data: "2025-01-17"},
    {id: 6, prodotto: "Tastiera", categoria: "elettronica", prezzo: 75, quantità: 4, data: "2025-01-17"},
    {id: 7, prodotto: "Lampada", categoria: "mobili", prezzo: 45, quantità: 3, data: "2025-01-18"}
];

// === ANALYTICS FUNCTIONS ===

// 1. Ricavi totali
const ricaviTotali = vendite
    .map(v => v.prezzo * v.quantità)
    .reduce((acc, ricavo) => acc + ricavo, 0);

console.log(`💰 Ricavi totali: €${ricaviTotali.toLocaleString()}`);

// 2. Ricavi per categoria
const ricaviPerCategoria = vendite
    .reduce((acc, v) => {
        const ricavo = v.prezzo * v.quantità;
        acc[v.categoria] = (acc[v.categoria] || 0) + ricavo;
        return acc;
    }, {});

console.log("\n📊 Ricavi per categoria:");
Object.entries(ricaviPerCategoria).forEach(([cat, ricavo]) => {
    console.log(`  ${cat}: €${ricavo.toLocaleString()}`);
});

// 3. Prodotto più venduto (per quantità)
const prodottoPiùVenduto = vendite
    .reduce((max, v) => v.quantità > max.quantità ? v : max);

console.log(`\n🏆 Prodotto più venduto: ${prodottoPiùVenduto.prodotto} (${prodottoPiùVenduto.quantità} unità)`);

// 4. Top 3 prodotti per ricavo
const top3Ricavi = vendite
    .map(v => ({
        prodotto: v.prodotto,
        ricavo: v.prezzo * v.quantità
    }))
    .sort((a, b) => b.ricavo - a.ricavo)
    .slice(0, 3);

console.log("\n🥇 Top 3 prodotti per ricavo:");
top3Ricavi.forEach((item, i) => {
    console.log(`  ${i + 1}. ${item.prodotto}: €${item.ricavo.toLocaleString()}`);
});

// 5. Prezzo medio prodotti
const prezzoMedio = vendite
    .map(v => v.prezzo)
    .reduce((acc, p, i, arr) => {
        acc += p;
        return i === arr.length - 1 ? acc / arr.length : acc;
    }, 0);

console.log(`\n💵 Prezzo medio: €${prezzoMedio.toFixed(2)}`);

// 6. Vendite per giorno
const venditePerGiorno = vendite
    .reduce((acc, v) => {
        if (!acc[v.data]) {
            acc[v.data] = {
                transazioni: 0,
                ricavo: 0,
                prodotti: []
            };
        }
        acc[v.data].transazioni++;
        acc[v.data].ricavo += v.prezzo * v.quantità;
        acc[v.data].prodotti.push(v.prodotto);
        return acc;
    }, {});

console.log("\n📅 Vendite per giorno:");
Object.entries(venditePerGiorno).forEach(([data, stats]) => {
    console.log(`  ${data}:`);
    console.log(`    Transazioni: ${stats.transazioni}`);
    console.log(`    Ricavo: €${stats.ricavo.toLocaleString()}`);
    console.log(`    Prodotti: ${stats.prodotti.join(", ")}`);
});

// 7. Categoria dominante
const categoriaDominante = Object.entries(ricaviPerCategoria)
    .reduce((max, [cat, ricavo]) => {
        return ricavo > max.ricavo ? {categoria: cat, ricavo} : max;
    }, {categoria: "", ricavo: 0});

console.log(`\n👑 Categoria dominante: ${categoriaDominante.categoria} (€${categoriaDominante.ricavo.toLocaleString()})`);

// 8. Prodotti sopra prezzo medio
const sopraPrezzoMedio = vendite
    .filter(v => v.prezzo > prezzoMedio)
    .map(v => v.prodotto);

console.log(`\n💎 Prodotti sopra prezzo medio (€${prezzoMedio.toFixed(2)}):`);
console.log(`  ${sopraPrezzoMedio.join(", ")}`);

// 9. Statistiche complete
const stats = {
    totaleTransazioni: vendite.length,
    ricaviTotali: ricaviTotali,
    ricavoMedio: ricaviTotali / vendite.length,
    prezzoMedio: prezzoMedio,
    quantitàTotale: vendite.reduce((acc, v) => acc + v.quantità, 0),
    categorie: Object.keys(ricaviPerCategoria).length,
    giorniAttivi: Object.keys(venditePerGiorno).length
};

console.log("\n📈 STATISTICHE COMPLETE:");
console.log(`  Transazioni: ${stats.totaleTransazioni}`);
console.log(`  Ricavi totali: €${stats.ricaviTotali.toLocaleString()}`);
console.log(`  Ricavo medio/transazione: €${stats.ricavoMedio.toFixed(2)}`);
console.log(`  Prezzo medio prodotti: €${stats.prezzoMedio.toFixed(2)}`);
console.log(`  Unità vendute: ${stats.quantitàTotale}`);
console.log(`  Categorie: ${stats.categorie}`);
console.log(`  Giorni attivi: ${stats.giorniAttivi}`);

// Output:
// 💰 Ricavi totali: €5.348
// 
// 📊 Ricavi per categoria:
//   elettronica: €3.423
//   mobili: €1.925
// 
// 🏆 Prodotto più venduto: Mouse (5 unità)
// 
// 🥇 Top 3 prodotti per ricavo:
//   1. Laptop: €1.998
//   2. Monitor: €900
//   3. Scrivania: €400
// 
// 💵 Prezzo medio: €256.29
// 
// 📅 Vendite per giorno:
//   2025-01-15:
//     Transazioni: 2
//     Ricavo: €2.123
//     Prodotti: Laptop, Mouse
//   ... (continua)
// 
// 👑 Categoria dominante: elettronica (€3.423)
// 
// 💎 Prodotti sopra prezzo medio (€256.29):
//   Laptop, Monitor
// 
// 📈 STATISTICHE COMPLETE:
//   Transazioni: 7
//   Ricavi totali: €5.348
//   Ricavo medio/transazione: €764.00
//   Prezzo medio prodotti: €256.29
//   Unità vendute: 20
//   Categorie: 2
//   Giorni attivi: 4

💡 Tecniche Usate
  • map() – Calcola ricavi, estrae proprietà
  • filter() – Filtra per condizioni
  • reduce() – Somme, raggruppamenti, oggetti complessi
  • sort() – Ordinamenti per ranking
  • slice() – Top N elementi
  • Method chaining – Pipeline di trasformazioni
  • Object destructuring – Estrazione valori

💪 Esercizi Pratici

📝 Esercizio 1: Analisi Studenti

Obiettivo: Analizza array di studenti con voti

  • Calcola media voti di ogni studente
  • Trova studenti promossi (media ≥ 6)
  • Calcola media classe
  • Trova studente migliore

📝 Esercizio 2: Carrello E-commerce

Obiettivo: Gestisci carrello con sconti e totali

  • Calcola subtotale per prodotto
  • Applica sconto categoria “elettronica” (10%)
  • Calcola totale carrello
  • Aggiungi spedizione gratuita se > €100

📝 Esercizio 3: Word Frequency

Obiettivo: Analizza testo e conta frequenza parole

  • Split testo in parole
  • Rimuovi punteggiatura e converti minuscolo
  • Conta occorrenze ogni parola
  • Ordina per frequenza e mostra top 5

🎯 Riepilogo Lezione

map()

  • Trasforma elementi
  • Stessa lunghezza
  • Return obbligatorio
filter()

  • Seleziona elementi
  • Return true/false
  • Lunghezza variabile
reduce()

  • Aggrega valori
  • Valore singolo
  • Valore iniziale!
Chaining

  • Concatena metodi
  • Pipeline dati
  • Filtra prima!

Lezione 11 del Corso JavaScript Completo

Torna in alto