[英]JavaScript: Removing duplicates in an array of arrays
目前使用JavaScript,我需要通过一个数组数组来确定是否有任何重复的数组,然后删除这些重复的数组。 在这种情况下,运行时是至关重要的,所以我想知道最有效的方法是什么。
在这种情况下使用哈希表是否合适? 这样做的范围是散列每个序列,然后使用散列来确定该序列是否再次出现。 因此,每个序列是主阵列中的一个阵列,任何重复序列都是同一阵列中的其他阵列。 此外,所有单个阵列本身保持有序非常重要(即各个阵列中的元素必须始终保持其位置)。 此外,单个数组中的所有元素都是字符串值。
示例:假设有一个数组A,其元素依次为以下数组:
A[0] = ["one", "two", "three", "four"]
A[1] = ["two", "one", "three", "four"]
A[2] = ["one", "two", "three", "four"]
在上面的例子中,A [0]和A [2]是重复的,因此函数应该返回A [0]和A [1],这样只有一个相同数组的实例。
保持一个对象,其中键是每个数组的连接元素。 如果未找到密钥,请将数组添加到输出数组并将密钥添加到对象。
var hash = {};
var out = [];
for (var i = 0, l = A.length; i < l; i++) {
var key = A[i].join('|');
if (!hash[key]) {
out.push(A[i]);
hash[key] = 'found';
}
}
好吧,让我们先来看看天真解决方案的复杂性:如果有n个数组,每个数组最多有k个条目,则需要进行O(n^2 * k)
比较,因为对于这n个数组中的每一个,你都有将它与n-1个进行比较,每个进行k次比较。 空间复杂度为O(n*k)
因此,如果您愿意交换空间以获得更好的性能,您可以执行以下操作:(简短免责声明:我假设您的所有阵列都有相同数量的k元素,这些元素已指明但未经您的问题批准。)
将一个一个地通过数组,你挑我们假设是第一要素a
。 使用哈希映射来验证您是否将此元素视为之前的第一个元素。 如果没有,请创建一个以其根为根的树结构, a
其存储在哈希映射中的a
下,并使其成为当前节点。 现在,对于当前数组中的每个后续条目,检查当前节点是否具有该类型的子节点。 因此,如果第二个条目是b
,则将b
添加为a的子级。
你的树现在看起来像这样:(从左到右:root到孩子)
a - b
将c
作为第三个条目的工作方式完全相同:
a - b - c
现在我们跳过去查看一个数组[a, c, d]
。 您首先遇到元素a
的树。 对于第二个元素,检查c
是否已经是a的子元素。 如果没有,请添加它:
- b - c
a
- c
同样适用于下一个条目:
- b - c
a
- c - d
现在让我们看看当我们检查之前看到的数组时会发生什么: [a, b, c]
首先我们检查a
,看看已经存在一棵树并从哈希映射中获取它。 接下来,我们注意到a
有一个名为b
的子节点,所以我们下降到b
。 现在,对于最后一个条目,我们看到它已经存在,告诉我们我们遇到了一个我们可以删除的副本。
对于即兴绘画,我很抱歉,我希望我可以了解这个想法。 它只是通过每个数组一次,以非冗余的方式存储它。 所以时间复杂度为O(n*k)
。 使用的空间增加但受O(n*k)
因为最坏的情况是没有数组共享任何前缀,这导致相同的空间复杂度。
希望我没有忽视一些事情。
A.filter((r={},a=>!(r[a]=++r[a]|0)))
我假设你的字符串不包含,
字符。 如果包含然后更改两次r[a]
到r[a.join('|')]
(其中|
是任意分隔符)或使用r[a.map(x=>x.length+','+x)]
来允许字符串中的所有字符。 这是一个有效的例子 。
说明
在r={}
我们设置一次临时对象。 在过滤函数a=>...
,仅用于在参数r={}
声明一次空临时对象。 在函数a=>...
中a
我们有一个当前的A
元素。 该JS做隐式转换a
以字符串r[a]
然后在!(r[a]=++r[a]|0)
,如果元素a
第一次出现,我们增加出现元素a
计数器并返回true(作为过滤函数值)。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.