如何获得 JavaScript 中具有重复值的两个数组之间的差异
How to get the difference between two arrays in JavaScript with repeating values
如何检查一个数组是否包含在另一个数组中以及 return 缺失值?我找到了执行此操作的方法 in this post 但 none 考虑了数组中的重复值。例如,我正在尝试做这样的事情:
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"]
一种可能的方法:
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
数组 - 并将新项目添加到 diff
diffedCounter
中缺失的每个副本的结果数组。但是这个特定的实现有一个缺陷:因为它使用 Object 来收集计数,所以它在计算元素时不区分 3
作为数字和 '3'
作为字符串。
这可以通过两种不同的方式解决:切换到 Map(但这会使代码更复杂,因为没有诸如递减 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]) );
如何检查一个数组是否包含在另一个数组中以及 return 缺失值?我找到了执行此操作的方法 in this post 但 none 考虑了数组中的重复值。例如,我正在尝试做这样的事情:
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"]
一种可能的方法:
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
数组 - 并将新项目添加到 diff
diffedCounter
中缺失的每个副本的结果数组。但是这个特定的实现有一个缺陷:因为它使用 Object 来收集计数,所以它在计算元素时不区分 3
作为数字和 '3'
作为字符串。
这可以通过两种不同的方式解决:切换到 Map(但这会使代码更复杂,因为没有诸如递减 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]) );