Gestire disponibilità e prenotazioni con map, filter e reduce in JavaScript

by Anastasia P.
SHARE
Gestire disponibilità e prenotazioni con map, filter e reduce in JavaScript
© Guida-HTML5.it

Introduzione

Le funzioni di ordine superiore permettono di passare una funzione come argomento a un’altra funzione. In JavaScript, map, filter e reduce sono tra gli strumenti più utili per lavorare con gli array in modo dichiarativo, leggibile e facilmente componibile.

In questo tutorial realizzeremo un esempio pratico: la gestione delle disponibilità di un calendario per un sistema di prenotazioni. Partiremo da una lista di slot orari, individueremo quelli prenotati, filtreremo gli orari ancora liberi e calcoleremo alcuni riepiloghi, come il numero totale di ore disponibili.

L’esempio è utile per applicazioni come calendari per studi professionali, sistemi di prenotazione di sale riunioni, appuntamenti medici e piattaforme per lezioni individuali.

Codice completo

const slots = [
  { id: 1, giorno: "Lunedì", ora: "09:00", durata: 1, prenotato: false },
  { id: 2, giorno: "Lunedì", ora: "10:00", durata: 1, prenotato: true },
  { id: 3, giorno: "Lunedì", ora: "11:00", durata: 1, prenotato: false },
  { id: 4, giorno: "Martedì", ora: "09:30", durata: 1.5, prenotato: false },
  { id: 5, giorno: "Martedì", ora: "11:00", durata: 1, prenotato: true },
  { id: 6, giorno: "Mercoledì", ora: "14:00", durata: 2, prenotato: false }
];

// filter: mantiene solo gli slot non prenotati
const slotDisponibili = slots.filter(slot => !slot.prenotato);

// map: crea una rappresentazione più adatta all´interfaccia
const etichetteDisponibilita = slotDisponibili.map(slot => ({
  id: slot.id,
  descrizione: `${slot.giorno} alle ${slot.ora}`,
  durataOre: slot.durata
}));

// reduce: calcola il numero complessivo di ore disponibili
const oreDisponibili = slotDisponibili.reduce(
  (totale, slot) => totale + slot.durata,
  0
);

// reduce: raggruppa gli slot disponibili per giorno
const disponibilitaPerGiorno = slotDisponibili.reduce((gruppo, slot) => {
  if (!gruppo[slot.giorno]) {
    gruppo[slot.giorno] = [];
  }

  gruppo[slot.giorno].push(slot);
  return gruppo;
}, {});

// map + filter: crea una lista di giorni che hanno almeno uno slot libero
const giorniConDisponibilita = [...new Set(
  slotDisponibili.map(slot => slot.giorno)
)].filter(giorno => giorno.length > 0);

console.log("Slot disponibili:", slotDisponibili);
console.log("Etichette:", etichetteDisponibilita);
console.log("Ore disponibili:", oreDisponibili);
console.log("Disponibilità per giorno:", disponibilitaPerGiorno);
console.log("Giorni disponibili:", giorniConDisponibilita);

Spiegazione

Usare filter per trovare gli slot liberi

filter restituisce un nuovo array contenente solo gli elementi che rispettano una condizione. Non modifica l’array originale, caratteristica importante quando vogliamo conservare tutti i dati ricevuti da un’API o da un database.

const slotDisponibili = slots.filter(slot => !slot.prenotato);

La funzione freccia restituisce true quando la proprietà prenotato vale false. Di conseguenza, gli slot già prenotati vengono esclusi. È possibile aggiungere condizioni più specifiche:

const slotDelLunedi = slots.filter(slot =>
  slot.giorno === "Lunedì" && !slot.prenotato
);

Usare map per trasformare i dati

map percorre ogni elemento e costruisce un nuovo array con il risultato della trasformazione. È ideale quando i dati originali contengono più informazioni di quelle necessarie per la visualizzazione.

const etichetteDisponibilita = slotDisponibili.map(slot => ({
  id: slot.id,
  descrizione: `${slot.giorno} alle ${slot.ora}`,
  durataOre: slot.durata
}));

Qui trasformiamo ogni slot in un oggetto più semplice. La proprietà descrizione può essere mostrata direttamente in un pulsante o in una scheda del calendario.

Usare reduce per calcolare un totale

reduce combina tutti gli elementi di un array in un unico risultato. Il secondo argomento della funzione, chiamato accumulatore, rappresenta il valore costruito durante l’iterazione.

const oreDisponibili = slotDisponibili.reduce(
  (totale, slot) => totale + slot.durata,
  0
);

Il valore iniziale è 0. A ogni passaggio viene aggiunta la durata dello slot corrente. Il risultato finale, in questo caso, è il numero complessivo di ore ancora prenotabili.

Raggruppare i dati con reduce

Un uso molto potente di reduce consiste nel creare un oggetto organizzato per categorie. Nell’esempio, ogni giorno diventa una proprietà dell’oggetto finale:

const disponibilitaPerGiorno = slotDisponibili.reduce((gruppo, slot) => {
  if (!gruppo[slot.giorno]) {
    gruppo[slot.giorno] = [];
  }

  gruppo[slot.giorno].push(slot);
  return gruppo;
}, {});

È fondamentale restituire sempre l’accumulatore, cioè gruppo. Senza questa istruzione, alla successiva iterazione l’accumulatore diventerebbe undefined.

Best practice

  • Non modificare l’array originale: preferisci map, filter e reduce quando vuoi produrre nuovi dati senza effetti collaterali.
  • Dai nomi descrittivi: variabili come slotDisponibili e oreDisponibili rendono il codice autoesplicativo.
  • Usa il valore iniziale in reduce: specifica sempre 0, [] o {}, in base al risultato desiderato.
  • Evita callback troppo complesse: se la logica diventa lunga, estraila in una funzione con un nome significativo.
  • Controlla i dati in ingresso: verifica che durata sia numerica e che ogni slot contenga le proprietà necessarie.
  • Considera la leggibilità: una catena di molte operazioni può essere elegante, ma più variabili intermedie possono facilitare il debug.

Riepilogo

In una gestione di disponibilità, filter seleziona gli slot liberi, map trasforma i dati in un formato adatto all’interfaccia e reduce calcola totali o raggruppamenti. La combinazione di questi metodi consente di scrivere codice compatto senza rinunciare alla chiarezza.

Ricorda la regola principale: usa map quando vuoi trasformare, filter quando vuoi selezionare e reduce quando vuoi ottenere un unico risultato o costruire una struttura aggregata.

Approfondisci con risorse ufficiali

SHARE