Reputation: 589
I have the following 2 arrays:
arr1 = [
{
"key1": "Value1"
},
{
"key2": "Value2"
},
{
"key3": "Test3"
},
{
"key4": "Test4"
},
{
"key5": "Test5"
},
{
"key6": "Test6"
},
{
"key7": "Test7"
}
]
And the second array is
arr2 = [
{
"key3": "Value3-changed"
},
{
"key6": "Value6-changed"
}
]
Now once I join the 2 arrays the result would be
resultArr = [
{
"key1": "Value1"
},
{
"key2": "Value2"
},
{
"key3": "Value3-changed"
},
{
"key4": "Test4"
},
{
"key5": "Test5"
},
{
"key6": "Value6-changed"
},
{
"key7": "Test7"
}
]
I saw the solution for Lodash union of arrays of objects. But as for my case, the keys are different. Any, pointers on solving this issue? I was trying to use lodash _.unionBy and then _.uniqWith but not getting the desired result.
Thanks, Andy
Upvotes: 2
Views: 3774
Reputation: 706
If you have access to the ...
spread operator:
map(chunk(toPairs(assign(...arr1, ...arr2))), fromPairs)
Otherwise:
map(chunk(toPairs(spread(assign)(concat(arr1, arr2)))), fromPairs)
Which is ugly but does the job.
_.mixin({
'assignPairsChunkAndMapObjects' : function(arr1, arr2) {
return _.map(_.chunk(_.toPairs(_.assign(...arr1, ...arr2))), _.fromPairs);
},
'assignPairsChunkAndMapObjectsChained' : function(arr1, arr2) {
return _.chain(_.assign(...arr1, ...arr2)).toPairs().chunk().map(_.fromPairs).value();
}
});
Upvotes: 1
Reputation: 10262
You can also use map
and find
method of array.
In ES5
var arr1 = [{
"key1": "Value1"
}, {
"key2": "Value2"
}, {
"key3": "Test3"
}, {
"key4": "Test4"
}, {
"key5": "Test5"
}, {
"key6": "Test6"
}, {
"key7": "Test7"
}],
arr2 = [{
"key3": "Value3-changed"
}, {
"key6": "Value6-changed"
}],
key = '';
var result = arr1.map(function(item) {
key = Object.keys(item)[0];
return arr2.find(function(v) {
return v[key]
}) || item;
});
console.log(result);
In ES6
const arr1 = [{
"key1": "Value1"
}, {
"key2": "Value2"
}, {
"key3": "Test3"
}, {
"key4": "Test4"
}, {
"key5": "Test5"
}, {
"key6": "Test6"
}, {
"key7": "Test7"
}],
arr2 = [{
"key3": "Value3-changed"
}, {
"key6": "Value6-changed"
}
];
let result = arr1.map(item => {
let key = Object.keys(item)[0];
return arr2.find(v => v[key]) || item;
});
console.log(result);
Upvotes: 0
Reputation: 48693
You can create a mixin to iterate over the first array and merge it with the second one.
_.mixin({
'mergeObjectList' : function(arr1, arr2) {
return _.map(arr1, function(obj) {
Object.keys(obj).forEach(key => {
var found = _.find(arr2, x => Object.keys(x).indexOf(key) > -1);
if (found != null) {
return _.merge(obj, found);
}
});
return obj;
});
}
});
var arr1 = [
{ "key1": "Value1" },
{ "key2": "Value2" },
{ "key3": "Test3" },
{ "key4": "Test4" },
{ "key5": "Test5" },
{ "key6": "Test6" },
{ "key7": "Test7" }
];
var arr2 = [
{ "key3": "Value3-changed" },
{ "key6": "Value6-changed" }
];
var arr3 = _.mergeObjectList(arr1, arr2);
document.body.innerHTML = JSON.stringify(arr3, null, 4);
body { font-family: monospace; white-space: pre; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.5/lodash.min.js"></script>
Upvotes: 0
Reputation: 4897
No lodash needed. First reduce both arrays to a single object, where keys coming later overwrite any previously set values:
const obj = [...arr1, ...arr2].reduce((acc,cur) => Object.assign(acc, cur), {});
// {key1: value1, ...}
Edit, even simpler:
const obj = Object.assign({}, ...arr1, ...arr2);
Then map the keys back to an array of objects:
const resultArray = Object.keys(obj)
.sort() // if alphanumeric order of keys matters to you
.map(key => { const o={}; o[key]=obj[key]; return o;});
Upvotes: 2
Reputation: 50336
With native javascript you can achieve the same using for ..in
& map function
var arr1 = [{
"key1": "Value1"
},
{
"key2": "Value2"
},
{
"key3": "Test3"
},
{
"key4": "Test4"
},
{
"key5": "Test5"
},
{
"key6": "Test6"
},
{
"key7": "Test7"
}
]
var arr2 = [{
"key3": "Value3-changed"
},
{
"key6": "Value6-changed"
}
];
// get object keys from both
var getArr2Keys = arr2.map(function(items) {
for (let keys in items) {
return keys;
}
});
var getArr1Keys = arr1.map(function(items) {
for (let keys in items) {
return keys;
}
});
// iterate over the newly created object and check if the key matched
getArr2Keys.forEach(function(itemArr2, index) {
var x = getArr1Keys.findIndex(function(itemArr1) {
return itemArr2 === itemArr1;
})
// replace the key value of arr1 with value from arr2
arr1[x][itemArr2] = arr2[index][itemArr2]
})
console.log(arr1)
Upvotes: 0
Reputation: 23174
You can do this without lodash like this :
(pushes new objects, or update existing one.
let arr1 = [
{
"key1": "Value1"
},
{
"key2": "Value2"
},
{
"key3": "Test3"
},
{
"key4": "Test4"
},
{
"key5": "Test5"
},
{
"key6": "Test6"
},
{
"key7": "Test7"
},
]
let arr2 = [
{
"key3": "Value3-changed"
},
{
"key6": "Value6-changed"
},
{
"key10": "Value10-new"
},
]
for (let obj of arr2) {
let keyName = Object.keys(obj)[0];
let existingObject = arr1.find(x => Object.keys(x)[0] === keyName );
if (existingObject) {
// object with same key exists. So we update it.
existingObject[keyName] = obj[keyName];
} else {
// key was not found, this is a new object, let's add it.
arr1.push(obj);
}
}
console.log(arr1)
There is probably a more elegant way to do that, of course.
Upvotes: 1