Home > database >  Flatten array of objects
Flatten array of objects

Time:11-13

I have an array of objects coming from a formData serializeArray function. For example:

[
        0 : {name: 'animal_monkey', value: 'banana'}
        1 : {name: 'animal_horse', value: 'radishes'}
        2 : {name: 'fruit_banana', value: 'yellow'}
        3 : {name: 'fruit_apple', value: 'red'}
]

I am looking for a way to get these different elements into a single object, split by category with their appropriate value assigned, like so:

{ 
        animal: { 
                        monkey : banana,
                        horse : radishes
                },
        fruit: {
                        banana : yellow,
                        apple : red
               }
}

I have tried doing this with reduce and Object assign, like so

obj = keys.map((k, i) => k.reduceRight((value, key) => ({[key]: value}), vals[i]) )
result = Object.assign({}, ...obj)

where keys is an array of ['animal_monkey', 'animal_horse', 'fruit_banana', 'fruit_apple'] and vals is a list with values: ['banana', 'radishes', 'yellow', 'red']. However, perhaps as expected, the values are overwritten and I end up with:

{ 
        animal: { 
                        horse : radishes
                },
        fruit: {
                        apple : red
               }
}

The first value(s) don't survive the assignment. Does anyone have a good idea how to make this work?

Thanks!

CodePudding user response:

You can split each name on _ and then create an object with the category and animal name using array#reduce.

const data = [ {name: 'animal_monkey', value: 'banana'}, {name: 'animal_horse', value: 'radishes'}, {name: 'fruit_banana', value: 'yellow'}, {name: 'fruit_apple', value: 'red'} ],
      result = data.reduce((r,o) => {
            const [category, name] = o.name.split('_');
            r[category] ??= {};
            r[category][name] = o.value;
            return r;
      }, {});
console.log(result);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<iframe name="sif1" sandbox="allow-forms allow-modals allow-scripts" frameborder="0"></iframe>

CodePudding user response:

You can set a variable that will hold the final combined object, then add to it for each element in the array using array.forEach

let single = {};
arr.forEach(obj => {
  let [catagory, name] = obj.name.split('_'); // catagory = before the _, name = after the _
  single[catagory] ??= {}; // make sure the catagory exists as an object in single
  single[catagory][name] = obj.value;
}
  • Related