我看到很多关于如何在 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)
我建议这个解决方案,它避免了O(n\xc2\xb2)的时间复杂度:
\n\nfunction 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此解决方案Map为第一个数组 ( a ) 的每个不同值创建一个键,并将每个值的出现次数作为值。然后以相同的方式将b添加到该Map值中,只不过出现次数为负数。如果该计数最终为零,那么这个键当然不应该出现在最终结果中。Map事实上,最终结果中出现的次数是其每个键的计数的绝对值。
代码开头为:
\n\nnew Map()\nRun Code Online (Sandbox Code Playgroud)\n\n它是内部累加器的初始值reduce。它reduce会迭代a并更新 中相应键的计数Map。最终的结果reduce是这样的Map。
然后,这Map将成为外部的初始累加器值reduce。迭代breduce并减少 中的计数。Map
更新后的数据Map通过展开运算符展开到一个数组中。该数组由 2 元素子数组组成,它们是键/值对。请注意,本例中的值是一个计数,可以是正数、零或负数。
然后用最终的 迭代该数组reduce。每个计数用于创建一个包含相应值的多个元素(以绝对值形式)的数组。所有这些都连接到一个数组,作为函数的返回值。
在评论中,您解释说您实际上需要不同的东西,其中两个数组的作用不同。应返回第一个数组,但从中删除第二个数组中的元素。
\n\n您可以使用此代码:
\n\nnew Map()\nRun Code Online (Sandbox Code Playgroud)\r\n| 归档时间: |
|
| 查看次数: |
1102 次 |
| 最近记录: |