[英]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.