2013-02-07 18 views
0

我有一個列表:如何從列表中刪除相似但不重複的項目?

values = [[6.23234121,6.23246575],[1.352672,1.352689],[6.3245,123.35323,2.3]] 

什麼辦法,我可以通過這個列表,刪除是內說0.01在同一列表中的其他元素的所有項目。

我知道如何做一個特定的列表使用del,但我希望它是一般如果值有n個列表中,每個列表有n個元素。

我希望發生的是這個名單

values = [[6.23234121,6.23246575],[1.352672,1.352689],[6.3245,123.35323,2.3]] 

上進行一些操作,讓這個輸出

new_values = [[6.23234121],[1.352672],[6.3245,123.35323,2.3]] 
+0

你能提供一些樣本輸入和輸出嗎? – StarPinkER

+1

你想要什麼'[0,0.005,0.01,0.015,0.02]'返回?每個元素都有一個在0.01之內的元素。 – DSM

回答

1

我打算寫一個函數來對一個列表做到這一點,例如:

>>> compact([6.23234121,6.23246575], tol=.01) 
[6.23234121] 

然後,您可以通過[compact(l) for l in lst]使它在嵌套結構上工作。

這些方法中的每一個都會使列表中沒有任何東西的第一個元素更接近它;對於@ DSM的例子[0, 0.005, 0.01, 0.015, 0.02],他們都會返回[0, 0.0.15](或者,如果您將>切換爲>=,[0, 0.01, 0.02])。如果你想要不同的東西,你必須確切地定義它更仔細。


首先,簡單的方法,類似於大衛的回答。這是O(n^2):

def compact(lst, tol): 
    new = [] 
    for el in lst: 
     if all(abs(el - x) > tol for x in new): 
      new.append(el) 
    return compact 

在三元素列表,這是完全好的。如果你想在三百萬個元素的清單上做到這一點,那不會削減它。讓我們嘗試不同的東西:

import collections 
import math 

def compact(lst, tol): 
    round_digits = -math.log10(tol) - 1 
    seen = collections.defaultdict(set) 
    new = [] 
    for el in lst: 
     rounded = round(seen, round_digits) 
     if all(abs(el - x) > tol for x in seen[rounded]): 
      seen[rounded].add(el) 
      new.append(el) 
    return new 

如果您tol0.01,然後round_digits爲1所以6.23234121seen剛剛6.2索引。當我們看到6.23246575時,我們將其四捨五入到6.2,並在索引中查找,該索引應包含所有可能在我們查找的數量的tol之內的數字。然後,我們仍然需要檢查這些數字的距離,但只能檢查該索引庫中的少數數字,而不是整個列表。

這種方法是O(n k),其中k是將落在一個這樣的箱內的平均元件數量。它只會有幫助,如果k < < n(因爲它通常會,但這取決於您使用的數字相對於tol分佈)。請注意,它也可能使用比其他方法多兩倍的內存,這可能是非常大的列表的問題。


另一種選擇是先對列表進行排序;那麼你只需要查看以前和以後的元素來檢查衝突。