Reputation: 70
I want to reorder this array:
[{ a: "v1", b: "v2"} , {a: "v3", b: "v4"}]
to this:
{a: ["v1", "v3"] , b: ["v2", "v4"]}
Note: It is necessary to guarantee order, the first array element should be the first element in the array value in each key object
Upvotes: 0
Views: 1489
Reputation: 9985
Another (short) lodash solution, using a combination of reduce
and mergeWith
:
_.reduce(data, (acc, x) => _.mergeWith(acc, x,
(obj = [], src) => obj.concat(src)),
{});
Or a bit more readable:
const customizer = (obj = [], src) => obj.concat(src);
_.reduce(data, (acc, x) => _.mergeWith(acc, x, customizer), {});
Or even:
const customizer = (obj = [], src) => obj.concat(src);
_.reduce(data, _.partialRight(_.mergeWith, customizer), {});
Upvotes: 0
Reputation: 30098
Here's a lodash solution that uses the combination of spread and mergeWith to merge all the objects with similar properties.
var result = _.spread(_.mergeWith)([{}].concat(data,
_.flow(_.ary(_.concat, 2), _.compact)
));
var data = [{
a: "v1",
b: "v2"
}, {
a: "v3",
b: "v4"
}, {
a: "v5",
b: "v6",
c: "1"
}];
var result = _.spread(_.mergeWith)([{}].concat(data,
_.flow(_.ary(_.concat, 2), _.compact)
));
console.log(result);
body>div {
min-height: 100%;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.js"></script>
Upvotes: 0
Reputation: 92854
Alternative solution using Array.prototype.reduce()
and Object.keys()
function:
var arr = [{ a: "v1", b: "v2"} , {a: "v3", b: "v4"}],
result = arr.reduce(function (r, o) {
Object.keys(o).forEach(function(k){ (r[k])? r[k].push(o[k]) : r[k] = [o[k]]; });
return r;
}, {});
console.log(result);
Upvotes: 0
Reputation: 12637
An extended Version of @Kind user's code, that also deals with objects that have different keys:
function mapByKey(source){
var result = Object.create(null);
source.forEach((item, index) => {
if(item == null) return;
Object.keys(item).forEach(key => {
if(!(key in result)){
//don't use sparse Arrays
result[key] = Array(source.length).fill(undefined);
}
result[key][index] = item[key];
})
})
return result;
}
var array = [
{a: "v1", b: "v2"},
{a: "v3", c: "v4"},
{b: "v5", c: "v7"}
];
var mapping = mapByKey(array);
console.log(mapping);
//or something funny:
console.log(mapByKey(["foo", "bar", "baz", "asdf"]));
The point of this version, is that even if your Array contains Objects with different keys (like in the example, one object has a
and b
, one has a
and c
and one has b
and c
), this will always be true:
array[index][key] === mapping[key][index];
Upvotes: 0
Reputation: 41893
Pure js solution, using Array#forEach
and Object.keys
.
var arr = [{ a: "v1", b: "v2"} , {a: "v3", b: "v4"}],
obj = {};
arr.forEach(c => Object.keys(c).forEach(function(v){
(obj[v] || (obj[v] = [])).push(c[v]);
}));
console.log(obj);
Upvotes: 1