2

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!

3
  • 1
    Could you design a better data structure? { type: 'animal', name: 'monkey', food: 'banana' }, for example. Might make things easier. Commented Nov 12, 2021 at 18:30
  • 1
    If there's more than one monkey in the data, you'll face data loss with the structure you want to get. Commented Nov 12, 2021 at 18:33
  • Thanks guys; no other monkeys in the data, so I’m not worried about data loss (I had encountered this before so took out other monkeys). Andy, your suggestion makes sense, but the data is coming from a serializeArray call, which only gives me name and value of the form; right now, animal and horse are encoded as ‘animal_horse’ as name, while value is ‘radishes’. Commented Nov 13, 2021 at 14:47

2 Answers 2

2

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; }

Sign up to request clarification or add additional context in comments.

3 Comments

Thanks! This looks promising—I’ll give it a go later today and let you know how it works out :)
Awesome! This did the job very nicely. Quick question: I have worked with Javascript before, but haven't seen the ??= operator before; is that a new one? What does it do? Also, I have always struggled trying to understand reduce. Any good pointers on that? Thanks!
?? is nullish coalesing operator. You can refer MDN to understand about array reduce.
1

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;
}

2 Comments

Also a good suggestion! I’ll test this one as well! Thanks to all!
This works well too! And I can totally see how it is a good alternative to the above answer, the difference of course being the use of reduce versus forEach. Is there any downside to using either? Is forEach for example more efficient than reduce?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.