如何比较两个数组并返回它们的差异?(双向工作?)

3
所以我想在纯的ES6 JS中实现这个。请不要使用jQuery!(接受Lodash!)
基本上,我有两个数组,一个包含对象,另一个包含ID。
const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
];

const newIds = [1, 2, 3];

这个问题的解决方法如下所示: const difference = newIds.filter(n => !old.some(o => o.id === n)); 这将返回[3]
基本上,我当前使用它来确定是否有丢失的内容,并在数据库中创建它们(如果确实缺少)。
但是,我需要做相反的操作。如果某些东西被删除了,我需要比较并删除该项。
这个问题在于:这个解决方案仅适用于“一种方式”,因此我无法执行上述操作。
理想情况下,不管是创建还是删除,我只需要一个语句,它只返回任一数组中缺失的内容的ID。
希望这能解释清楚。

1
既然您写了“Lodash可行”,请在您的问题中添加[tag:lodash]标记:这样,关注(或“观察”)该标记的用户就可以看到您的问题。 - Gerardo Furtado
1
如果您不想构建复杂的逻辑,可以使用Lodash JS库轻松找到数组的差异。 - Sanjaysinh Zala
@SanjaysinhZala 也许可以举个例子?我尝试使用 Lodash 的 difference 方法,但它的工作方式不符合我的预期。 - user5113508
7个回答

3
使用 Lodash 的方法找出在一个集合中出现而在另一个集合中没有出现的值。
_.xor(array1, array2);

根据您的情况:

> const _ = require('lodash');

> const old = [
...   { id: 1, name: 'object_1' },
...   { id: 2, name: 'object_2' },
...   { id: 3, name: 'object_3' },
...   { id: 4, name: 'object_4' },
... ];

> const newIds = [1, 3, 5, 7];

> _.xor(old.map(x => x.id), newIds)
[ 2, 4, 5, 7 ]

1
我们可以使用 Array#filterArray#includes 在原生的es6中完成相同的操作。
这里,我通过使用Array#map将旧数组映射到仅包含id的数组,然后在两个数组上使用过滤器和包含器找出它们之间的对称差异。

const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
];
const newIds = [2, 3];
const oldIds =  old.map(({id}) => id);

console.log(getDifference(oldIds, newIds));

function getDifference(oldIds, newIds){
  const diff = [...oldIds.filter(id => !newIds.includes(id)), ...newIds.filter(id => !oldIds.includes(id))];
  return diff;
}

We can do it another way using Array#reduce and Array#findIndex. Just reduce over both the arrays and return the elements which are not repeated more than once will give us the symmetric difference of the two arrays.

const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
];
const newIds = [2, 3];
const oldIds =  old.map(({id}) => id);

console.log(getDifference(oldIds, newIds));

function getDifference(oldIds, newIds){
  return [...oldIds, ...newIds].reduce((acc, ele) => {
  if(!acc.includes(ele)){
     acc.push(ele);
  }else{
    acc.splice(acc.findIndex(e=> ele === e), 1);
  }
  return acc;
  },[]);
}


0

你可以使用 Lodash 中的 xor 函数来实现这个功能。 在此之前,你可以从 old 数组中收集所有的 id,并将这些 id 用于 xor

看一下这个例子。

const { xor } = _;
const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
  {
    id: 4,
    name: 'object_4',
  },
];

const newIds = [1, 2, 3];
const oldIds = old.map(o => o.id)
const diff = xor(newIds, oldIds);
console.log(diff)
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>


0
希望这可以帮到你。我知道这不完全是你想要的,但这可以是一个解决方法。

const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
  {
    id: 4,
    name: 'object_2',
  },
];

const newIds = [1, 2, 3];

var x1 = old.filter(x => !newIds.includes(x.id)).map(z => z.id)
             .concat(newIds.filter(x => !old.some(y => y.id === x)));
console.log(x1);


0
这是使用ES6的解决方案:

const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
  {
    id: 4,
    name: 'object_2',
  },
];

const newIds = [1, 2, 3];
const oldIds = old.map(o => o.id)

const difference = [...newIds.filter(id => oldIds.indexOf(id) === -1), ...oldIds.filter(id => newIds.indexOf(id) === -1)]

console.log(difference)


0
你可以使用带有默认值的 _.get 作为 _.differenceBy 的迭代器,这样对象数组或数字数组都可以在左侧。

const old = [
  {
    id: 1,
    name: 'object_1',
  },
  {
    id: 2,
    name: 'object_2',
  },
];

const newIds = [1, 2, 3];

const diff = (a,b) => _.differenceBy(a, b, v => _.get(v, 'id', v))
console.log({ remove: diff(old, newIds), add: diff(newIds, old) })

const otherNewIds = [1];
console.log({ remove: diff(old, otherNewIds), add: diff(otherNewIds, old) })
<script src="https://cdnjs.cloudflare.com/ajax/libs/lodash.js/4.17.11/lodash.min.js"></script>


0
以下代码将使用lodash查找差异:
const difference = _.difference(newIds, _.map(old, 'id'));

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接