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
Top comments (31)
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
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..."
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?
Nice!
I had to write one of these the other day.
Here's a slightly more concise version, where you throw out extra brackets and use an implicit return 😄 :
the
[item[key]]
tripped me up initially haha.Thanks so much for pointing this out Brad! I have used this syntax for one liner map functions but had overlooked using it with reduce before. I am going to make sure I use it in the future, to keep my code more concise.
Thanks man💪
So long as you don't have to support older browsers, or are using Babel, new ES features do this without the need of a helper function. See the MDN docs for Object.fromEntires.
Thanks Paul, I have done some reading on this feature a few months back but hadn't seen how I could apply this to my problem.
There is another comment from ygorbunkov which demonstrates how to do this so I will have a reference point if I need to use something similar again soon!
I 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)
I faced out with this problem and I took as a reference: stackoverflow.com/a/44325124
And I created some similar that your solution but with less lines and more faster
Thanks for the reference their artezan, the explanations in those answers have really helped my understanding!
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:
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
reduceHere'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
: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 }
}
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
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!
Thanks man. this really helpful for me