使用 lodash 或下划线的唯一对象数组和合并重复项
Unique array of objects and merge duplications using lodash or underscore
我有一个可以包含重复项的对象数组,但我想通过 属性 唯一化该数组,然后我想有条件地合并重复项的属性。例如,给出下面的数组
var array = [
{
name: 'object1',
propertyA: true,
propertyB: false,
propertyC: false
},
{
name: 'object2',
propertyA: false,
propertyB: true,
propertyC: false
},
{
name: 'object1',
propertyA: false,
propertyB: true,
propertyC: false
}
]
知道每个对象都有名称 属性A、属性B 和 属性C,我想用名称 属性 来唯一化,并保留属性A、属性B 和 属性C 的真实值。所以上面的数组变成了,
var updatedArray = [
{
name: 'object1',
propertyA: true,
propertyB: true,
propertyC: false
},
{
name: 'object2',
propertyA: false,
propertyB: true,
propertyC: false
}
]
使用 lodash/underscore 解决此问题的最佳方法是什么?
使用纯 Javascript,您可以使用散列 table 作为对具有相同名称的唯一对象的引用,并在键上循环收集值并使用逻辑或更新。
var array = [{ name: 'object1', propertyA: true, propertyB: false, propertyC: false }, { name: 'object2', propertyA: false, propertyB: true, propertyC: false }, { name: 'object1', propertyA: false, propertyB: true, propertyC: false }],
unique = array.reduce(function (hash) {
return function (r, a) {
if (!hash[a.name]) {
hash[a.name] = { name: a.name };
r.push(hash[a.name]);
}
Object.keys(a).forEach(function (k) {
if (k !== 'name') {
hash[a.name][k] = hash[a.name][k] || a[k];
}
});
return r;
};
}(Object.create(null)), []);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用 _.uniqWith
来做到这一点,但它需要您在返回它们是否相等的布尔值之前改变其中一个参数,所以我不推荐它。
更好的选择是使用_.groupBy
followed by _.map
in order to group the unique names, and then customize how you combine them. In your case, you can combine the same-named objects using _.assignWith
,然后给出逻辑或||
运算作为组合函数。
使用 ES6,它几乎变成了一行代码:
var array = [{"name":"object1","propertyA":true,"propertyB":false,"propertyC":false},{"name":"object2","propertyA":false,"propertyB":true,"propertyC":false},{"name":"object1","propertyA":false,"propertyB":true,"propertyC":false}];
var updatedArray =
_(array)
.groupBy('name')
.map(objs => _.assignWith({}, ...objs, (val1, val2) => val1 || val2))
.value();
console.log(updatedArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>
我有一个可以包含重复项的对象数组,但我想通过 属性 唯一化该数组,然后我想有条件地合并重复项的属性。例如,给出下面的数组
var array = [
{
name: 'object1',
propertyA: true,
propertyB: false,
propertyC: false
},
{
name: 'object2',
propertyA: false,
propertyB: true,
propertyC: false
},
{
name: 'object1',
propertyA: false,
propertyB: true,
propertyC: false
}
]
知道每个对象都有名称 属性A、属性B 和 属性C,我想用名称 属性 来唯一化,并保留属性A、属性B 和 属性C 的真实值。所以上面的数组变成了,
var updatedArray = [
{
name: 'object1',
propertyA: true,
propertyB: true,
propertyC: false
},
{
name: 'object2',
propertyA: false,
propertyB: true,
propertyC: false
}
]
使用 lodash/underscore 解决此问题的最佳方法是什么?
使用纯 Javascript,您可以使用散列 table 作为对具有相同名称的唯一对象的引用,并在键上循环收集值并使用逻辑或更新。
var array = [{ name: 'object1', propertyA: true, propertyB: false, propertyC: false }, { name: 'object2', propertyA: false, propertyB: true, propertyC: false }, { name: 'object1', propertyA: false, propertyB: true, propertyC: false }],
unique = array.reduce(function (hash) {
return function (r, a) {
if (!hash[a.name]) {
hash[a.name] = { name: a.name };
r.push(hash[a.name]);
}
Object.keys(a).forEach(function (k) {
if (k !== 'name') {
hash[a.name][k] = hash[a.name][k] || a[k];
}
});
return r;
};
}(Object.create(null)), []);
console.log(unique);
.as-console-wrapper { max-height: 100% !important; top: 0; }
您可以使用 _.uniqWith
来做到这一点,但它需要您在返回它们是否相等的布尔值之前改变其中一个参数,所以我不推荐它。
更好的选择是使用_.groupBy
followed by _.map
in order to group the unique names, and then customize how you combine them. In your case, you can combine the same-named objects using _.assignWith
,然后给出逻辑或||
运算作为组合函数。
使用 ES6,它几乎变成了一行代码:
var array = [{"name":"object1","propertyA":true,"propertyB":false,"propertyC":false},{"name":"object2","propertyA":false,"propertyB":true,"propertyC":false},{"name":"object1","propertyA":false,"propertyB":true,"propertyC":false}];
var updatedArray =
_(array)
.groupBy('name')
.map(objs => _.assignWith({}, ...objs, (val1, val2) => val1 || val2))
.value();
console.log(updatedArray);
.as-console-wrapper { max-height: 100% !important; top: 0; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.4/lodash.min.js"></script>