Javascript: raggruppa array di oggetti in base a valori comuni con etichetta
Sto cercando di trasformare un array di oggetti in un altro array di oggetti raggruppandoli per un valore specifico e aggiungendo quel valore come etichetta ed estraendolo dall'oggetto nel nuovo array.
Input: Quindi, ad esempio, ho questo array di oggetti:
let tech = [
{ id: 1, grouping: "Front End", value: "HTML" },
{ id: 2, grouping: "Front End", value: "React" },
{ id: 3, grouping: "Back End", value: "Node" },
{ id: 4, grouping: "Back End", value: "PHP" },
];
Previsto: sto cercando di capire come posso arrivare a questo, dove c'è un'etichetta per ciascuno dei raggruppamenti univoci e l'array di opzioni contenente i valori di quel raggruppamento.
[
{
label: "Front End",
options: [
{ id: 1, value: "HTML" },
{ id: 2, value: "React" },
],
},
{
label: "Back End",
options: [
{ id: 3, value: "Node" },
{ id: 4, value: "PHP" },
],
},
]
Il più vicino a cui sono stato in grado di arrivare è usare la riduzione al gruppo tramite la chiave di raggruppamento:
const groupedTech = tech.reduce((acc, value) => {
// Group initialization
if (!acc[value.grouping]) {
acc[value.grouping] = [];
}
// Grouping
acc[value.grouping].push(value);
return acc;
}, {});
Il che mi dà questo:
{
"Front End": [
{ id: 1, grouping: "Front End", value: "HTML" },
{ id: 2, grouping: "Front End", value: "React" },
],
"Back End": [
{ id: 3, grouping: "Back End", value: "Node" },
{ id: 4, grouping: "Back End", value: "PHP" },
],
}
Ma questo restituisce un oggetto non un array e non rimuove il valore di raggruppamento. Non sono stato in grado di capire come raggruppare correttamente perché nell'array di oggetti non ho trovato un modo efficiente per confrontarmi per vedere se il raggruppamento esiste e in tal caso aggiungerlo a quell'array annidato. Sarei meglio usare qualcosa come .map () ? Apprezza eventuali contatti / apprendimenti!
Risposte
Sei molto vicino, racchiudi semplicemente le voci dei valori-chiave del risultato che hai ottenuto in una mapfunzione:
let tech = [
{ id: 1, grouping: "Front End", value: "HTML" },
{ id: 2, grouping: "Front End", value: "React" },
{ id: 3, grouping: "Back End", value: "Node" },
{ id: 4, grouping: "Back End", value: "PHP" },
];
const groupedTech = Object.entries(
// What you have done
tech.reduce((acc, { id, grouping, value }) => {
// Group initialization
if (!acc[grouping]) {
acc[grouping] = [];
}
// Grouping
// FIX: only pushing the object that contains id and value
acc[grouping].push({ id, value });
return acc;
}, {})
).map(([label, options]) => ({ label, options }));
console.log(groupedTech);
Devi solo fare un'altra manipolazione con Object.entriese.map
let tech = [
{ id: 1, grouping: 'Front End', value: 'HTML' },
{ id: 2, grouping: 'Front End', value: 'React' },
{ id: 3, grouping: 'Back End', value: 'Node' },
{ id: 4, grouping: 'Back End', value: 'PHP' }
]
const groupedTech = tech.reduce((acc, value) => {
// Group initialization
if (!acc[value.grouping]) {
acc[value.grouping] = []
}
// Grouping
acc[value.grouping].push(value)
return acc
}, {})
const res = Object.entries(groupedTech).map(([label, options]) => ({
label,
options
}))
console.log(res)
Una piccola variazione sulle altre due risposte se vuoi ottenere esattamente l'output che specifichi:
let tech = [{
id: 1,
grouping: "Front End",
value: "HTML"
},
{
id: 2,
grouping: "Front End",
value: "React"
},
{
id: 3,
grouping: "Back End",
value: "Node"
},
{
id: 4,
grouping: "Back End",
value: "PHP"
},
];
const groupedTech = Object.entries(
tech.reduce((acc, value) => {
// Group initialization
if (!acc[value.grouping]) {
acc[value.grouping] = [];
}
// Grouping
acc[value.grouping].push({
id: acc[value.grouping].length+1,
value: value.value
});
return acc;
}, {}))
.map(([label, options]) => ({
label,
options
}));
console.log(groupedTech);
Di solito mi piace creare una Mapcoppia chiave / valore e poi trasformare quelle voci nel risultato finale (di solito usando Array.prototype.map()o Array.from()).
const tech = [
{ id: 1, grouping: "Front End", value: "HTML" },
{ id: 2, grouping: "Front End", value: "React" },
{ id: 3, grouping: "Back End", value: "Node" },
{ id: 4, grouping: "Back End", value: "PHP" },
];
const groupedMap = tech.reduce((map, { grouping, ...option }) => {
if (!map.has(grouping)) {
map.set(grouping, [])
}
map.get(grouping).push(option)
return map
}, new Map())
const groupedTech = Array.from(groupedMap, ([ label, options ]) => ({
label,
options
}))
console.log(groupedTech)
Utilizzo di una mappa e dei valori di mappa # ()
const grouped = tech.reduce((m,{grouping:label, ...rest})=>{
const group = m.get(label) || {label, options:[]};
group.options.push({...rest})
return m.set(label, group)
},new Map)
console.log([...grouped.values()])
<script>
let tech=[{id:1,grouping:"Front End",value:"HTML"},{id:2,grouping:"Front End",value:"React"},{id:3,grouping:"Back End",value:"Node"},{id:4,grouping:"Back End",value:"PHP"}];
</script>