Javascript 使用 Lodash 按属性合并对象数组
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/39127565/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Merge Array of Objects by Property using Lodash
提问by benjiman
I have two arrays of objects that represent email addresses that have a label and a value:
我有两个对象数组,它们表示具有标签和值的电子邮件地址:
var original = [
{
label: 'private',
value: '[email protected]'
},
{
label: 'work',
value: '[email protected]'
}
];
var update = [
{
label: 'private',
value: '[email protected]'
},
{
label: 'school',
value: '[email protected]'
}
];
Now I want to compare and merge the two arrays by the label
field, so that the result would look like this:
现在我想按label
字段比较和合并两个数组,结果如下所示:
var result = [
{
label: 'private',
value: '[email protected]'
},
{
label: 'work',
value: '[email protected]'
},
{
label: 'school',
value: '[email protected]'
}
]
How can I do this e.g. using lodash?
我怎样才能做到这一点,例如使用lodash?
回答by Andreas
_.unionBy()
:
This method is like _.union except that it accepts iteratee which is invoked for each element of each arrays to generate the criterion by which uniqueness is computed. Result values are chosen from the first array in which the value occurs.
_.unionBy()
:
此方法类似于 _.union,除了它接受为每个数组的每个元素调用的 iteratee 以生成计算唯一性的标准。结果值是从出现该值的第一个数组中选择的。
var original = [
{ label: 'private', value: '[email protected]' },
{ label: 'work', value: '[email protected]' }
];
var update = [
{ label: 'private', value: '[email protected]' },
{ label: 'school', value: '[email protected]' }
];
var result = _.unionBy(update, original, "label");
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.min.js"></script>
回答by Tamas Hegedus
Convert the lists to objects keyed by label
, merge them by _.assign
, and convert it back to an array. It will even retain order of the items on most browsers.
将列表转换为以 为键的对象,通过label
合并它们_.assign
,然后将其转换回数组。它甚至会保留大多数浏览器上项目的顺序。
var original = [
{
label: 'private',
value: '[email protected]'
},
{
label: 'work',
value: '[email protected]'
}
];
var update = [
{
label: 'private',
value: '[email protected]'
},
{
label: 'school',
value: '[email protected]'
}
];
console.log(
_.map(
_.assign(
_.mapKeys(original, v => v.label),
_.mapKeys(update, v => v.label)
)
)
);
// or remove more duplicated code using spread
console.log(
_.map(
_.assign(
...[original, update].map(
coll => _.mapKeys(coll, v => v.label)
)
)
)
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>
回答by Ralph
Perhaps a bit late, but all the solutions I have seen don't join both arrays correctly, they use one of the arrays to loop on and any excess elements in the second array don't get added (assuming this is what is required).
也许有点晚了,但我看到的所有解决方案都没有正确连接两个数组,它们使用其中一个数组进行循环,并且不会添加第二个数组中的任何多余元素(假设这是必需的) .
The right way is to sort both arrays and move forward within both arrays, merging the matches elements and adding the missing elements from both arrays. Please find full solution below. This also takes O(n+m) which is the best you can get (without the computational costs for sort itself). In my code I already got the data sorted from the database.
正确的方法是对两个数组进行排序并在两个数组中向前移动,合并匹配元素并添加两个数组中缺失的元素。请在下面找到完整的解决方案。这也需要 O(n+m),这是您可以获得的最佳结果(没有排序本身的计算成本)。在我的代码中,我已经从数据库中得到了排序的数据。
function mergeObjectsBasedOnKey(array1, array2, compareFn, mergeFn, alreadySorted) {
var array1Index = 0;
var array2Index = 0;
const merged = [];
if (!alreadySorted) {
array1.sort(compareFn);
array2.sort(compareFn);
}
while (array1Index < array1.length && array2Index < array2.length) {
var comparedValue = compareFn(array1[array1Index], array2[array2Index]);
if (comparedValue === 0) {
merged.push(mergeFn(array1[array1Index], array2[array2Index]));
array1Index++;
array2Index++;
} else if (comparedValue < 0) {
merged.push(mergeFn(array1[array1Index]));
array1Index++;
} else {
merged.push(mergeFn(array2[array2Index]));
array2Index++;
}
}
while (array1Index < array1.length) {
merged.push(mergeFn(array1[array1Index]));
array1Index++;
}
while (array2Index < array2.length) {
merged.push(mergeFn(array2[array2Index]));
array2Index++;
}
return merged;
}
const array1 = [{
"id": 10,
isArray1: true
},
{
"id": 11,
isArray1: true
},
{
"id": 12,
isArray1: true
},
];
const array2 = [{
"id": 8,
isArray2: true
},
{
"id": 11,
isArray2: true
},
{
"id": 15,
isArray2: true
},
];
const result = mergeObjectsBasedOnKey(array1, array2, function(a, b) {
return a.id - b.id;
}, function(a, b) {
if (b) {
return _.merge(a, b);
}
return _.merge(a, {
isArray1: true,
isArray2: true
});
});
console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
And the results would be:
结果将是:
[ { id: 8, isArray2: true, isArray1: true },
{ id: 10, isArray1: true, isArray2: true },
{ id: 11, isArray1: true, isArray2: true },
{ id: 12, isArray1: true, isArray2: true },
{ id: 15, isArray2: true, isArray1: true } ]
回答by Revanth Kumar
I know it is not what asked for but just in case someone stumbled up on this page here is how you do this in ramda:
我知道这不是所要求的,但以防万一有人在此页面上偶然发现了您在 ramda 中执行此操作的方法:
var original = [
{ label: 'private', value: '[email protected]' },
{ label: 'work', value: '[email protected]' }
];
var updated = [
{ label: 'private', value: '[email protected]' },
{ label: 'school', value: '[email protected]' }
];
unionWith(eqBy(prop('label')), updated, original);
回答by Manish Kumar
In case you are using lodash 3.x where _.unionBy()was not there, you can combine _.union()
and _.uniq()
to get the same result.
如果您正在使用 lodash 3.x 而_.unionBy()不存在,您可以组合_.union()
并_.uniq()
获得相同的结果。
var original = [
{ label: 'private', value: '[email protected]' },
{ label: 'work', value: '[email protected]' }
];
var update = [
{ label: 'private', value: '[email protected]' },
{ label: 'school', value: '[email protected]' }
];
var result = _.uniq(_.union(update, original), "label");
console.log(result);
回答by jain77
Here is another way to merge two objects using Lodash:
这是使用 Lodash 合并两个对象的另一种方法:
let a = [{
content: 'aaa',
name: 'bbb2'
},
{
content: 'aad',
name: 'ccd'
}
];
let b = [{
content: 'aaa',
name: 'bbb'
},
{
content: 'aad1',
name: 'ccd1'
}
];
let c = [...a, ...b];
let d = _.uniq(c, function(data) {
return data.content;
})
console.log(d);
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>