使用Lodash按属性合并对象数组

时间:2016-08-24 15:35:55

标签: javascript arrays merge lodash

我有两个对象数组,表示具有标签和值的电子邮件地址:

var original = [
  {
    label: 'private',
    value: 'private@johndoe.com'
  },
  {
    label: 'work',
    value: 'work@johndoe.com'
  }
];

var update = [
  {
    label: 'private',
    value: 'me@johndoe.com'
  },
  {
    label: 'school',
    value: 'schhol@johndoe.com'
  }
];

现在我想通过label字段比较和合并两个数组,以便结果如下所示:

var result = [
  {
    label: 'private',
    value: 'me@johndoe.com'
  },
  {
    label: 'work',
    value: 'work@johndoe.com'
  },
  {
    label: 'school',
    value: 'schol@johndoe.com'
  }
]

我该怎么做呢,例如使用lodash

6 个答案:

答案 0 :(得分:71)

_.unionBy()
此方法与_.union类似,不同之处在于它接受为每个数组的每个元素调用的iteratee,以生成计算唯一性的标准。 从值中出现值的第一个数组中选择结果值

var original = [
  { label: 'private', value: 'private@johndoe.com' },
  { label: 'work', value: 'work@johndoe.com' }
];

var update = [
  { label: 'private', value: 'me@johndoe.com' },
  { label: 'school', value: 'schol@johndoe.com' }
];

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>

答案 1 :(得分:4)

将列表转换为label键入的对象,将它们合并为_.assign,然后将其转换回数组。它甚至会保留大多数浏览器上的项目顺序。

&#13;
&#13;
var original = [
  {
    label: 'private',
    value: 'private@johndoe.com'
  },
  {
    label: 'work',
    value: 'work@johndoe.com'
  }
];

var update = [
  {
    label: 'private',
    value: 'me@johndoe.com'
  },
  {
    label: 'school',
    value: 'schol@johndoe.com'
  }
];

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)
      )
    )
  )
);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.15.0/lodash.js"></script>
&#13;
&#13;
&#13;

答案 2 :(得分:1)

如果您使用的是lodash 3.x,其中 _。unionBy()不存在,您可以将_.union()_.uniq()结合使用以获得相同的结果。< / p>

var original = [
  { label: 'private', value: 'private@johndoe.com' },
  { label: 'work', value: 'work@johndoe.com' }
];

var update = [
  { label: 'private', value: 'me@johndoe.com' },
  { label: 'school', value: 'schol@johndoe.com' }
];

var result = _.uniq(_.union(update, original), "label"); 

console.log(result);

答案 3 :(得分:0)

这是使用Lodash合并两个对象的另一种方法:

&#13;
&#13;
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);
&#13;
<script src="https://cdnjs.cloudflare.com/ajax/libs/underscore.js/1.9.1/underscore-min.js"></script>
&#13;
&#13;
&#13;

答案 4 :(得分:0)

我知道这不是要问的问题,但是以防万一,有人在此页面上绊倒了,这是您在ramda中的操作方法:

var original = [
  { label: 'private', value: 'private@johndoe.com' },
  { label: 'work', value: 'work@johndoe.com' }
];

var updated = [
  { label: 'private', value: 'me@johndoe.com' },
  { label: 'school', value: 'schol@johndoe.com' }
];

unionWith(eqBy(prop('label')), updated, original);

答案 5 :(得分:0)

也许有点晚,但是我看到的所有解决方案都无法正确加入两个数组,它们使用一个数组进行循环,并且第二个数组中的任何多余元素都不会添加(假设这就是是必需的。

我也有同样的发现,所以我自己整理了一些东西。这适用于我的用例,如果'label'字段的值匹配,则合并每个对象:

const dataSetHashes = dataSets.map(dataSet => _.keyBy(dataSet, 'label'))
const resultHash = _.merge(
  {},
  ...dataSetLookups
)
const result = Object.values(resultLookup)