transform object to array with lodash
JavascriptArraysObjectLodashJavascript Problem Overview
How can I transform a big object
to array
with lodash?
var obj = {
22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[],}
12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[],}
}
// transform to
var arr = [{name:"John", id:22...},{name:"Ivan", id:12...}]
Javascript Solutions
Solution 1 - Javascript
Solution 2 - Javascript
A modern native solution if anyone is interested:
const arr = Object.keys(obj).map(key => ({ key, value: obj[key] }));
or (not IE):
const arr = Object.entries(obj).map(([key, value]) => ({ key, value }));
Solution 3 - Javascript
_.toArray(obj);
Outputs as:
[ { "name": "Ivan", "id": 12, "friends": [ 2, 44, 12 ],
"works": {
"books": [],
"films": []
}
},
{
"name": "John",
"id": 22,
"friends": [
5,
31,
55
],
"works": {
"books": [],
"films": []
}
}
]"
Solution 4 - Javascript
For me, this worked:
_.map(_.toPairs(data), d => _.fromPairs([d]));
It turns
{"a":"b", "c":"d", "e":"f"}
into
[{"a":"b"}, {"c":"d"}, {"e":"f"}]
Solution 5 - Javascript
There are quite a few ways to get the result you are after. Lets break them in categories:
ES6 Values only:
Main method for this is Object.values. But using Object.keys and Array.map you could as well get to the expected result:
Object.values(obj)
Object.keys(obj).map(k => obj[k])
var obj = {
A: {
name: "John"
},
B: {
name: "Ivan"
}
}
console.log('Object.values:', Object.values(obj))
console.log('Object.keys:', Object.keys(obj).map(k => obj[k]))
ES6 Key & Value:
Using map and ES6 dynamic/computed properties and destructuring you can retain the key and return an object from the map.
Object.keys(obj).map(k => ({[k]: obj[k]}))
Object.entries(obj).map(([k,v]) => ({[k]:v}))
var obj = {
A: {
name: "John"
},
B: {
name: "Ivan"
}
}
console.log('Object.keys:', Object.keys(obj).map(k => ({
[k]: obj[k]
})))
console.log('Object.entries:', Object.entries(obj).map(([k, v]) => ({
[k]: v
})))
Lodash Values only:
The method designed for this is _.values
however there are "shortcuts" like _.map
and the utility method _.toArray
which would also return an array containing only the values from the object. You could also _.map
though the _.keys
and get the values from the object by using the obj[key]
notation.
Note: _.map
when passed an object would use its baseMap
handler which is basically forEach
on the object properties.
_.values(obj)
_.map(obj)
_.toArray(obj)
_.map(_.keys(obj), k => obj[k])
var obj = {
A: {
name: "John"
},
B: {
name: "Ivan"
}
}
console.log('values:', _.values(obj))
console.log('map:', _.map(obj))
console.log('toArray:', _.toArray(obj))
console.log('keys:', _.map(_.keys(obj), k => obj[k]))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Lodash Key & Value:
// Outputs an array with [[KEY, VALUE]]
_.entries(obj)
_.toPairs(obj)
// Outputs array with objects containing the keys and values
_.map(_.entries(obj), ([k,v]) => ({[k]:v}))
_.map(_.keys(obj), k => ({[k]: obj[k]}))
_.transform(obj, (r,c,k) => r.push({[k]:c}), [])
_.reduce(obj, (r,c,k) => (r.push({[k]:c}), r), [])
var obj = {
A: {
name: "John"
},
B: {
name: "Ivan"
}
}
// Outputs an array with [KEY, VALUE]
console.log('entries:', _.entries(obj))
console.log('toPairs:', _.toPairs(obj))
// Outputs array with objects containing the keys and values
console.log('entries:', _.map(_.entries(obj), ([k, v]) => ({
[k]: v
})))
console.log('keys:', _.map(_.keys(obj), k => ({
[k]: obj[k]
})))
console.log('transform:', _.transform(obj, (r, c, k) => r.push({
[k]: c
}), []))
console.log('reduce:', _.reduce(obj, (r, c, k) => (r.push({
[k]: c
}), r), []))
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>
Note that in the above examples ES6 is used (arrow functions and dynamic properties).
You can use lodash _.fromPairs
and other methods to compose an object if ES6 is an issue.
Solution 6 - Javascript
If you want the key (id in this case) to be a preserved as a property of each array item you can do
const arr = _(obj) //wrap object so that you can chain lodash methods
.mapValues((value, id)=>_.merge({}, value, {id})) //attach id to object
.values() //get the values of the result
.value() //unwrap array of objects
Solution 7 - Javascript
Transforming object to array with plain JavaScript's(ECMAScript-2016
) Object.values
:
var obj = {
22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}
var values = Object.values(obj)
console.log(values);
If you also want to keep the keys use Object.entries
and Array#map
like this:
var obj = {
22: {name:"John", id:22, friends:[5,31,55], works:{books:[], films:[]}},
12: {name:"Ivan", id:12, friends:[2,44,12], works:{books:[], films:[]}}
}
var values = Object.entries(obj).map(([k, v]) => ({[k]: v}))
console.log(values);
Solution 8 - Javascript
Object to Array
Of all the answers I think this one is the best:
let arr = Object.entries(obj).map(([key, val]) => ({ key, ...val }))
that transforms:
{
a: { p: 1, q: 2},
b: { p: 3, q: 4}
}
to:
[
{ key: 'a', p: 1, q: 2 },
{ key: 'b', p: 3, q: 4 }
]
Array to Object
To transform back:
let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { ...val }; return obj; }, {})
To transform back keeping the key in the value:
let obj = arr.reduce((obj, { key, ...val }) => { obj[key] = { key, ...val }; return obj; }, {})
Will give:
{
a: { key: 'a', p: 1, q: 2 },
b: { key: 'b', p: 3, q: 4 }
}
For the last example you can also use lodash _.keyBy(arr, 'key')
or _.keyBy(arr, i => i.key)
.
Solution 9 - Javascript
2017 update: Object.values, lodash values and toArray do it. And to preserve keys map and spread operator play nice:
// import { toArray, map } from 'lodash'
const map = _.map
const input = {
key: {
value: 'value'
}
}
const output = map(input, (value, key) => ({
key,
...value
}))
console.log(output)
// >> [{key: 'key', value: 'value'}])
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Solution 10 - Javascript
var arr = _.map(obj)
You can use _.map
function (of both lodash
and underscore
) with object
as well, it will internally handle that case, iterate over each value and key with your iteratee, and finally return an array. Infact, you can use it without any iteratee (just _.map(obj)
) if you just want a array of values. The good part is that, if you need any transformation in between, you can do it in one go.
Example:
var obj = {
key1: {id: 1, name: 'A'},
key2: {id: 2, name: 'B'},
key3: {id: 3, name: 'C'}
};
var array1 = _.map(obj, v=>v);
console.log('Array 1: ', array1);
/*Actually you don't need the callback v=>v if you
are not transforming anything in between, v=>v is default*/
//SO simply you can use
var array2 = _.map(obj);
console.log('Array 2: ', array2);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
However, if you want to transform your object you can do so, even if you need to preserve the key, you can do that ( _.map(obj, (v, k) => {...}
) with additional argument in map
and then use it how you want.
However there are other Vanilla JS solution to this (as every lodash
solution there should pure JS version of it) like:
Object.keys
and thenmap
them to valuesObject.values
(in ES-2017)Object.entries
and thenmap
each key/value pairs (in ES-2017)for...in
loop and use each keys for feting values
And a lot more. But since this question is for lodash
(and assuming someone already using it) then you don't need to think a lot about version, support of methods and error handling if those are not found.
There are other lodash solutions like _.values
(more readable for specific perpose), or getting pairs and then map and so on. but in the case your code need flexibility that you can update it in future as you need to preserve keys
or transforming values a bit, then the best solution is to use a single _.map
as addresed in this answer. That will bt not that difficult as per readability also.
Solution 11 - Javascript
If you want some custom mapping (like original Array.prototype.map) of Object into an Array, you can just use _.forEach
:
let myObject = {
key1: "value1",
key2: "value2",
// ...
};
let myNewArray = [];
_.forEach(myObject, (value, key) => {
myNewArray.push({
someNewKey: key,
someNewValue: value.toUpperCase() // just an example of new value based on original value
});
});
// myNewArray => [{ someNewKey: key1, someNewValue: 'VALUE1' }, ... ];
See lodash
doc of _.forEach https://lodash.com/docs/#forEach