Originally posted on afewminutesofcode.com
To convert an array into an object we will create a function and give it 2 properties, an array and a key.
const convertArrayToObject = (array, key) => {};
We will then reduce the array, and create a unique property for each item based on the key we have passed in.
We also need to remember to set an initial Value, and also pass in the current value (...obj in the below).
const convertArrayToObject = (array, key) => {
const initialValue = {};
return array.reduce((obj, item) => {
return {
...obj,
[item[key]]: item,
};
}, initialValue);
};
So now if we log out our function (passing in the array and our key which is a unique identifier in this case the id property) we will see our array is now an object.
console.log(
convertArrayToObject(
[
{ id: 111, name: 'John', age: 29 },
{ id: 112, name: 'Sarah', age: 25 },
{ id: 122, name: 'Kate', age: 22 },
{ id: 123, name: 'Tom', age: 21 },
{ id: 125, name: 'Emma', age: 24 },
],
'id',
),
);
returns
{
111:{ id: 111, name: 'John', age: 29 },
112:{ id: 112, name: 'Sarah', age: 25 },
122:{ id: 122, name: 'Kate', age: 22 },
123:{ id: 123, name: 'Tom', age: 21 },
125:{ id: 125, name: 'Emma', age: 24 }
}
We can now easily look up data in our array by an id and use it as required.
If you are looking for some more tips or want to be notified when my next post is available follow Me Online Here:
Instagram
Facebook
afewminutesofcode.com
Twitter
Pinterest
Latest comments (33)
can someone help how to get this output
a = [{id: 1, value: 1}, {id: 1, value: 2},
{id: 2, value: 20}, {id: 3, value: 30}]
output-->
{1: [{id: 1, value: 1}, {id: 1, value: 2}],
2: [{id: 2, value: 20}],3:[{id: 3, value: 30}]}
I know that this post is from 2019, but I guess I will offer some more recent way of writing this:
Or if you want to remove the key from the object:
Nice !
how to convert something having more than one value of id like below :
for this example i understand there wont be more than one id but in my case there will be same value.
to
{
111:[{ id: 111, name: 'John', age: 29 },{ id: 111, name: 'Rob', age: 29 },{ id: 111, name: 'Joe', age: 29 }]
112:{ id: 112, name: 'Sarah', age: 25 },
122:{ id: 122, name: 'Kate', age: 22 },
123:{ id: 123, name: 'Tom', age: 21 },
125:{ id: 125, name: 'Emma', age: 24 }
}
Thanks man. this really helpful for me
Here's type-friendly version in TypeScript
Notes:
• TypeScript 4.0+ (tested on 4.0.x and 4.1.x)
• for the 2nd arg TS will allow and suggest only those keys for which all objects hold a value of type
number
orstring
(only those types by which any object props can be indexed).So if all those objects had a prop
BD
with a string value for all the people, except John'sBD
was aDate
object, TS won't suggest nor allow you to choose'BD'
for the 2nd arg.• that single usage of
any
here is intentional. As a result, it's going to be collapsed, whereas usingunknown
would require several additional checks.• usage of
as
operator to assert the type of return value is intentional. May be unnecessary in future TypeScript versions.• works perfectly for variable data, but only almost perfect for constant data.
Here in this example if you denote that test array
as const
, TS will be able to tell you that the object has 5 properties111
,112
,122
,123
,125
, but won't be able to tell you which object exactly under each key and think its a union type of all objects for each key.So, given the passed array had
as const
annotation and the returned object from the example is calledfooobj
:Thank you, this was very handy.
I remixed it a little:
I should have mentioned that I've used the
lodash
reduce method here instead of thejavascript
reduceI have another example to wotk with your Code, but I didn't reach it.
My Array:
[
{"name":"Product 1","series":{"name":"Area 1","value":3}},
{"name":"Product 2","series":{"name":"Area 2","value":3}},
{"name":"Product 1","series":{"name":"Area 2","value":1}},
]
Need to convert it to an object like this:
[ {"name": "Product 1",
"series":[{"name":"Area 1","value":3},{"name":"Area 2","value":1}] },
{"name":"Product 2",
"series":[{"name":"Area 2","value":3}] }
];
It would be nice if you could give my any advice how to reach this by adopting your Code?
I would do something like this below to get the result (not nice or fast but should do the job :D):
const arr = [
{"name":"Product 1","series":{"name":"Area 1","value":3}},
{"name":"Product 2","series":{"name":"Area 2","value":3}},
{"name":"Product 1","series":{"name":"Area 2","value":1}},
];
const result = [... new Set(arr.map(x=>x.name))].map(x=>({"name":x,"series":[]}));
arr.forEach(x=>result.find(y=>y.name===x.name).series.push(x.series));
JSON.stringify(result,null,3);
Thank you this works very good.
I have one question:
what does arr.forEach(x=>result.find(y=>y.name===x.name).series.push(x.series));
I don't understand this function. I left it out and works. What does it?
It cannot work without it, it makes no sense. I've just generated array with unique names and empty series array at first (result), this one is pushing all the series objects data into these empty series arrays in result array.
It's just going through original array (arr) to pick series object and push it in result series array - names properties has to match hence y.name===x.name
to understand the code a bit better, how I have to adjust it to get the following result:
[
{"name":"Area 1","value":3},
{"name":"Area 2","value":3},
{"name":"Area 2","value":1}
];
From that?
let arr = [
{"name":"Product 1","series":{"name":"Area 1","value":3}},
{"name":"Product 2","series":{"name":"Area 2","value":3}},
{"name":"Product 1","series":{"name":"Area 2","value":1}},
]
U can just remap it
arr.map(x=>x.series)
One Vuejs style guide recommends to normalize array into object. This will come in super handy!! Thanks!
Good to hear! Also check out the comments as some awesome developers have taken the time to suggest some small improvements as well!
This is good, anyhow is an antipattern, it should be something like:
In this way, you avoid the spread op which is a way expensive than a single assignment
I was a bit surprised by your claim regarding the spread operator being anti-pattern so I asked around and it seems that there are different opinions regarding that. Would you care to throw in some info to shed more light on the topic?
Hey, man, I like code golfing too, but just because something can be written more concisely, it doesn't mean we should. Your second solution is kinda difficult to read because it's so cluttered and it also obligates people to know what the comma operator is and how it works. I just don't see how this is better than your first solution once the bundler will already minify the code for us, we don't need to write and read minified code, just be aware everyone, if you're gonna copy this, copy the first one, the people reading your code in the future will be happier :D
there is no item var around it should be curr did you even write that code alone?
Thanks for taking the time to help me and others out here! I am going to read up on the Comma operator in JavaScript developer.mozilla.org/en-US/docs/W... do you have any other resources you recomend here?
There is no comma operator here
yes, there is, it's right above the line of the "Basically everything..."
What about Object.fromEntries()?
const convertArrayToObject = (arr,propName) => Object.fromEntries(arr.map(({[propName]:prop,...rest}) => [prop, {...rest}]));
Thanks so much ygorbunkov, I have done some reading on this feature a few months back but hadn't seen how I could apply this to my problem, I will have a reference point if I need to use something similar again soon!
You shall bear in mind, though, it still works noticeably slower than
reduce()
. Hope, it will get optimised as this feature becomes more 'mainstream'.Thank you, I will keep this in mind. Have a great day