获取两个数组之间的差异(包括重复)

jdi*_*n04 8 javascript arrays

我看到很多关于如何在 javascript 中获取数组的差异和对​​称差异的帖子,但我没有找到任何关于如何找到差异的内容,包括重复项。

例如:

let original = [1];
let updated = [1, 1, 2];

difference(updated, original);
// Expect: [1, 2]
Run Code Online (Sandbox Code Playgroud)

有没有一种优雅的方法来做到这一点?我对使用普通 javascript 或 lodash 的解决方案持开放态度。

谢谢!

更新

为了澄清,应该支持无限数量的重复。另一个例子:

let original = [1, 1];
let updated = [1, 1, 1, 1, 1, 2];

difference(updated, original);
// Expect: [1, 1, 1, 2]
Run Code Online (Sandbox Code Playgroud)

更新 2

我意识到原来的要求可能有些混乱。确实应该支持无限重复,但顺序不应该影响输出。

例子:

let original = [1, 1, 2];
let updated = [1, 2, 1, 1, 1];

difference(updated, original);
// Expect: [1, 1]
Run Code Online (Sandbox Code Playgroud)

tri*_*cot 8

我建议这个解决方案,它避免了O(n\xc2\xb2)的时间复杂度:

\n\n

\r\n
\r\n
function difference(a, b) {\r\n    return [...b.reduce( (acc, v) => acc.set(v, (acc.get(v) || 0) - 1),\r\n            a.reduce( (acc, v) => acc.set(v, (acc.get(v) || 0) + 1), new Map() ) \r\n    )].reduce( (acc, [v, count]) => acc.concat(Array(Math.abs(count)).fill(v)), [] );\r\n}\r\n\r\nlet original = [1, 1];\r\nlet updated = [1, 1, 1, 1, 1, 2];\r\nlet res = difference(updated, original);\r\n\r\nconsole.log(res);
Run Code Online (Sandbox Code Playgroud)\r\n
\r\n
\r\n

\n\n

解释

\n\n

此解决方案Map为第一个数组 ( a ) 的每个不同值创建一个键,并将每个值的出现次数作为值。然后以相同的方式将b添加到该Map值中,只不过出现次数为负数。如果该计数最终为零,那么这个键当然不应该出现在最终结果中。Map事实上,最终结果中出现的次数是其每个键的计数的绝对值。

\n\n

细节

\n\n

代码开头为:

\n\n
new Map()\n
Run Code Online (Sandbox Code Playgroud)\n\n

它是内部累加器的初始值reduce。它reduce会迭代a并更新 中相应键的计数Map。最终的结果reduce是这样的Map

\n\n

然后,这Map将成为外部的初始累加器值reduce。迭代breduce并减少 中的计数。Map

\n\n

更新后的数据Map通过展开运算符展开到一个数组中。该数组由 2 元素子数组组成,它们是键/值对。请注意,本例中的值是一个计数,可以是正数、零或负数。

\n\n

然后用最终的 迭代该数组reduce。每个计数用于创建一个包含相应值的多个元素(以绝对值形式)的数组。所有这些都连接到一个数组,作为函数的返回值。

\n\n

后续问题

\n\n

在评论中,您解释说您实际上需要不同的东西,其中两个数组的作用不同。应返回第一个数组,但从中删除第二个数组中的元素。

\n\n

您可以使用此代码:

\n\n

\r\n\r\n
\r\n

\n