-2

如何检查一个数组是否包含在另一个数组中并返回缺失值?我在这篇文章中找到了执行此操作的方法,但没有一个方法可以解释数组中的重复值。例如,我正在尝试做这样的事情:

getDiff([1, 2, 3], [1, 2, 3, 4]) --> []

getDiff([1, 2, 2, 3], [1, 2, 3, 4]) --> [2]

getDiff(["A", "B", "C"], ["B", "B", "A", "C"]) --> []

getDiff(["B", "B", "B"], [3, 2, 1]) --> ["B", "B", "B"]
4

1 回答 1

1

一种可能的方法:

function getRepeatingDiff(source, diffed) {
  const diffedCounter = diffed.reduce((acc, el) => {
    acc[el] = (acc[el] || 0) + 1
    return acc;
  }, {});
  
  const diff = source.reduce((acc, el) => {
    return diffedCounter[el]-- > 0 ? acc : [ ...acc, el ];
  }, []);
  
  return diff;
}

console.log( getRepeatingDiff([1, 2, 3], [1, 2, 3, 4]) );
console.log( getRepeatingDiff([1, 3, 2, 2, 3], [1, 2, 3, 4]) );
console.log( getRepeatingDiff(["A", "B", "C"], ["B", "B", "A", "C"]) );
console.log( getRepeatingDiff(["B", "B", "B"], [3, 2, 1]) );

本质上,这是一个两步过程:计算diffed数组中的项目数,然后再遍历source一次数组 - 并diffdiffedCounter. 但是,这个特定的实现有一个缺陷:因为它使用 Object 来收集计数,所以在计算元素时它不区分3数字和'3'字符串。

这可以通过两种不同的方式解决:要么切换到 Map(但这会使代码更加复杂,因为没有诸如递减映射值之类的东西) - 或者在创建计数器键时只使用类型前缀。这是基于前者的方法:

function getRepeatingDiff(source, diffed) {
  const diffedCounter = diffed.reduce((map, el) => {
    const prev = map.get(el);
    return map.set(el, (prev || 0 ) + 1);
  }, new Map());
  
  const diff = source.reduce((acc, el) => {
    const remainingCount = diffedCounter.get(el);
    if (remainingCount) diffedCounter.set(el, remainingCount - 1);
    return remainingCount ? acc : [ ...acc, el ];
  }, []);
  
  return diff;
}

console.log( getRepeatingDiff([1, 2, 3], [1, 2, 3, 4]) );
console.log( getRepeatingDiff([1, 3, 2, 2, 3], [1, 2, 3, 4]) );
console.log( getRepeatingDiff(["A", "B", "C"], ["B", "B", "A", "C"]) );
console.log( getRepeatingDiff(["B", "B", "B"], [3, 2, 1]) );

于 2021-06-30T20:07:54.683 回答