【问题标题】:More efficient solution to find duplicate objects or arrays in Javascript?在 Javascript 中查找重复对象或数组的更有效解决方案?
【发布时间】:2018-08-03 11:58:46
【问题描述】:

我知道我可以实现如下解决方案:Remove duplicate objects from an array using javascript,即输出字符串的项目的串联。

但是,由于我的表示网络流的对象(或数组)必须在不同位置包含 4 个或更多项目(即源 IP、目标 IP、源端口、目标端口),因此连接在这里没有帮助,因为我应该创建 4 个排列字符串来比较它们。所以我试图了解是否存在更有效的解决方案。

假设在javascript中有以下4个对象:

1. { srcip: 192.168.1.10, dstip: 192.168.1.20, srcport: 5000, dstport: 443 }
2. { srcip: 192.168.1.20, dstip: 192.168.1.10, srcport: 443, dstport: 5000 }
3. { srcip: 192.168.1.10, dstip: 192.168.1.20, srcport: 5000, dstport: 80 }
4. { srcip: 192.168.1.30, dstip: 192.168.1.20, srcport: 5000, dstport: 443 }

只有对象 1 和 2 是重复的;换句话说,当对象的所有元素都相同时,对象就是重复的,即使它们被交换(源 IP 与目标 IP 和源端口与目标端口)。当然,同样的数据可以存储在数组中,没关系。

1. [192.168.1.10, 192.168.1.20, 5000, 443]
2. [192.168.1.20, 192.168.1.10, 443, 5000]
3. [192.168.1.10, 192.168.1.20, 5000, 80]
4. [192.168.1.30, 192.168.1.20, 5000, 443]

你知道如何解决这个问题吗?

更新

阅读您的 cmets 和解决方案,我只想添加一个说明。如果两对“IP/端口”相同,则一个对象必须与另一个对象相同,即使它们已交换。所以,如上所述,流程1和流程2应该相等,但下面的流程不同:

{ srcip: 192.168.1.20, dstip: 192.168.1.10, srcport: 5000, dstport: 443 }

因为相对于流 1,只有它的 IP 被交换(而不是端口)。

【问题讨论】:

  • 四个排列?如果 ip 保持不变但你切换端口它仍然是重复的?前任。 { srcip: 192.168.1.10, dstip: 192.168.1.20, srcport: 443, dstport: 5000 } 也是 1 和 2 的重复项?
  • 对象比较在 JS 中总是很微妙的。另见this thread。看起来 Lodash 有一个奇迹_.isEqual() 功能。
  • 因此,如果两个不同的键可以使其成为骗子,那么您需要做一些更复杂的事情。你编码把最小的数字放在第一位,等等。
  • @barbsan:我在帖子中添加了一个说明。 @JeremyThille:优秀的库和功能,我不知道。但是,如果我将该函数用于流 1 和 2,它将输出 false,但在我的情况下它们是重复的。

标签: javascript arrays object duplicates permutation


【解决方案1】:

首先创建 "{ip}:{port}" 之类的字符串(或使用除: 之外的任何其他分隔符),然后对它们进行排序并连接以获得单个字符串

var arr = [{ srcip: "192.168.1.10", dstip: "192.168.1.20", srcport: 5000, dstport: 443 },
 { srcip: "192.168.1.20", dstip: "192.168.1.10", srcport: 443, dstport: 5000 },
 { srcip: "192.168.1.10", dstip: "192.168.1.20", srcport: 5000, dstport: 80 },
 { srcip: "192.168.1.30", dstip: "192.168.1.20", srcport: 5000, dstport: 443 }
 ]
 
 var arrForRemovingDupes = arr.map(el => [el.srcip + ":" +el.srcport, el.dstip + ":" +el.dstport].sort().join())
 
 console.log(arrForRemovingDupes)

【讨论】:

  • 谢谢,您的解决方案可能是一个好方法。让我们等待一段时间,看看是否存在其他解决方案......否则我会接受你的! :)
【解决方案2】:

将上述数据存储在数组中,您可以对这些数组进行排序并连接以创建字符串键。使用键列表,您可以轻松找到重复项:

const data = [
  ['192.168.1.10', '192.168.1.20', 5000, 443],
  ['192.168.1.20', '192.168.1.10', 443, 5000],
  ['192.168.1.10', '192.168.1.20', 5000, 80],
  ['192.168.1.30', '192.168.1.20', 5000, 443],
]

const keys = data.map(item => item.sort().join());

输出:

[
  "192.168.1.10,192.168.1.20,443,5000",
  "192.168.1.10,192.168.1.20,443,5000", // equals to the previous one
  "192.168.1.10,192.168.1.20,5000,80",
  "192.168.1.20,192.168.1.30,443,5000"
]

如果您想将具有原始对象的它们分组,请尝试使用;

const grouped = data.reduce((acc, item) => {
  const key = item.sort().join();
  acc[key] = (acc[key] || []).concat([item]);
  return acc;
}, {});

【讨论】:

  • 感谢您的解决方案@hsz,但它也可能发生这种流程(抱歉,如果我没有在我的原始示例中包含):['192.168.1.20', '192.168.1.10', 5000, 443]。所以,这个流程不必等于流程 1 和 2。
猜你喜欢
  • 2013-11-22
  • 2018-06-12
  • 2021-05-06
  • 2018-12-18
  • 2013-09-05
  • 2016-12-13
  • 1970-01-01
  • 2014-08-08
  • 1970-01-01
相关资源
最近更新 更多