如何比较两个数组并返回差值? (双向工作?)

时间:2019-03-20 04:58:48

标签: javascript lodash

因此,我希望在普通的ES6 JS中实现这一目标。请不要jQuery! (Lodash是可以接受的!)

基本上我有2个数组,1个包含对象,1个包含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]

基本上,我目前正在使用它来确定是否缺少某些内容,如果缺少,请在我的数据库中创建它。

但是,我需要做相反的事情。如果删除了某些内容,则需要比较并删除该项目。

问题是;当前的解决方案仅适用于“ 1种方式”,因此我无法执行上述操作。

理想情况下,我只想要1条语句(无论是创建还是删除),并且只希望它返回两个数组中缺少的东西的ID。

希望这是有道理的。

7 个答案:

答案 0 :(得分:2)

要查找出现在一个而不是另一个中的值,请使用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 :(得分: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>

答案 2 :(得分: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);

答案 3 :(得分: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)

答案 4 :(得分: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>

答案 5 :(得分:0)

我们可以使用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;
}

我们可以使用Array#reduceArray#findIndex进行另一种方式。只需缩小两个数组并返回不重复一次的元素,就可以得出两个数组的对称差。

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;
  },[]);
}

答案 6 :(得分:0)

以下代码将使用lodash找到区别:

const difference = _.difference(newIds, _.map(old, 'id'));