I am trying to turn an array of objects into another array of objects by grouping by a specific value and adding that value as label and taking it out of the object in the new array.
Input: So for instance I have this array of objects:
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" },
];
Expected: I am looking to try and figure out how I can get to this, where there is a label for each of the unique groupings and options array containing the values of that grouping.
[
{
label: "Front End",
options: [
{ id: 1, value: "HTML" },
{ id: 2, value: "React" },
],
},
{
label: "Back End",
options: [
{ id: 3, value: "Node" },
{ id: 4, value: "PHP" },
],
},
]
The closest I have been able to get to is using reduce to group by the grouping key:
const groupedTech = tech.reduce((acc, value) => {
// Group initialization
if (!acc[value.grouping]) {
acc[value.grouping] = [];
}
// Grouping
acc[value.grouping].push(value);
return acc;
}, {});
Which gives me this:
{
"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" },
],
}
But this returns object not an array and doesn't remove the grouping value. I have not been able to figure out how to group properly because in the array of objects I have not found an efficient way to compare against to see if the grouping exists and if so add to that nested array. Would I be better off using something like .map() ? Appreciate any leads/learnings!
You're very close, just wrap the key-value entries of the result you've got in a map
function:
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);
You just have to do one more manipulation with Object.entries
and .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)
A minor variation on the other two answers if you want to get exactly the output you specify:
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);
I usually like to build up a Map
of key / value pairs then transform those entries into the final result (usually using Array.prototype.map()
or 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)
Using a Map and Map#values()
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>
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.