簡體   English   中英

JavaScript:刪除數組數組中的重復項

[英]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';
  }
}

DEMO

好吧,讓我們先來看看天真解決方案的復雜性:如果有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)因為最壞的情況是沒有數組共享任何前綴,這導致相同的空間復雜度。

希望我沒有忽視一些事情。

ONELINER

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.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM