使用 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>