如何使用Lodash的unionBy和合并嵌套数组?

时间:2018-11-20 14:52:45

标签: javascript arrays lodash array-merge

我要合并/合并数组中的对象,每个对象都带有一系列嵌套数组。我想基于特定键(此处为label[1])合并对象。我可以使用Lodash和unionBy来过滤label[1]所产生的重复项,但是如何保留已过滤项的值?

数组看起来像这样:

var arr = [{
    "label": ['item', 'private'],
    "values": [1, 2, 3]
  },
  {
    "label": ['item', 'private'],
    "values": [1, 2, 3, 6]
  },
  {
    "label": ['item', 'work'],
    "values": [1, 2, 8, 9]
  },
  {
    "label": ['item', 'private'],
    "values": [1, 2, 4, 5]
  },
  {
    "label": ['item', 'school'],
    "values": [1, 2, 7]
  }
];

所需的输出是:

var arr = [{
  "label": ["item", "private"],
  "values": [1, 2, 3, 4, 5, 6 ]
}, {
  "label": ["item", "work"],
  "values": [1, 2, 8, 9]
}, {
  "label": ["item", "school"],
  "values": [1, 2, 7]
}]

这里是一个样本,距离样本只有一半。

var arr = [
  { label: ['item','private'], values: [1,2,3] },
  { label: ['item','private'], values: [1,2,3,6] },
  { label: ['item','work'], values: [1,2,8,9] },
  { label: ['item','private'], values: [1,2,4,5] },
  { label: ['item','school'], values: [1,2,7] }
];

var result = _.unionBy(arr, "label[1]");

console.log(result);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

有什么想法吗?

谢谢 拉瑟

3 个答案:

答案 0 :(得分:1)

我会写:

const arr2 = _(arr)
    .groupBy("label")
    .map(objs => ({
        label: objs[0].label,
        values: _(objs).flatMap("values").uniq().value(),
    }))
    .value()

答案 1 :(得分:0)

不确定如何使用lodash进行此操作,但我不认为unionBy仍然是执行此操作的方法。

在这里,您可以使用lodash按标签进行分组,然后将组减少为一个值以合并组中的项目。

const arr = [{"label":["item","private"],"values":[1,2,3]},{"label":["item","private"],"values":[1,2,3,6]},{"label":["item","work"],"values":[1,2,8,9]},{"label":["item","private"],"values":[1,2,4,5]},{"label":["item","school"],"values":[1,2,7]}];

console.log(
  Object.values(
    _.groupBy(arr, (item) => item.label.join()),//use lodash group by
  ).map((
    group, //now we have array of array of groups
  ) =>
    group
      .reduce((result, item) => ({
        //reduce a group to one object
        label: result.label, //set label
        values: [
          //set values with unique values of all items
          ...new Set(
            (result.values || []).concat(item.values || []),
          ),
        ],
      })),
  ),
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.js"></script>

答案 2 :(得分:0)

您还可以通过 lodash 做类似的事情:

var arr = [{ "label": ['item', 'private'], "values": [1, 2, 3] }, { "label": ['item', 'private'], "values": [1, 2, 3, 6] }, { "label": ['item', 'work'], "values": [1, 2, 8, 9] }, { "label": ['item', 'private'], "values": [1, 2, 4, 5] }, { "label": ['item', 'school'], "values": [1, 2, 7] } ]

const merge = arr => _.reduce(arr, (r,c) => _.union(r, c.values), [])
const result = _(arr).groupBy('label')
 .entries()
 .reduce((r,[k,v]) => (r.push({ label: k.split(','), values: merge(v) }), r), [])

console.log(result)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.10/lodash.min.js"></script>

这个想法是首先通过_.groupBy进行分组,然后(通过_.entries获取条目,以便可以通过_.reduce形成所需的输出。 _.union,我们将值数组合并为最终reduce的一部分。

这是 ES6 的实现:

var arr = [{ "label": ['item', 'private'], "values": [1, 2, 3] }, { "label": ['item', 'private'], "values": [1, 2, 3, 6] }, { "label": ['item', 'work'], "values": [1, 2, 8, 9] }, { "label": ['item', 'private'], "values": [1, 2, 4, 5] }, { "label": ['item', 'school'], "values": [1, 2, 7] } ]

const mrg = arr => Array.from(new Set(arr.reduce((r,c) => [...r, ...c.values], [])))
const grp = (arr, k) => arr.reduce((r,c) => (r[c[k]] = [...r[c[k]] || [], c], r), {}) 
const result = Object.entries(grp(arr, 'label'))
  .reduce((r,[k,v]) => (r.push({ label: k.split(','), values: mrg(v) }), r), [])

console.log(result)