2013-02-07 20 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分布)。请注意,它也可能使用比其他方法多两倍的内存,这可能是非常大的列表的问题。


另一种选择是先对列表进行排序;那么你只需要查看以前和以后的元素来检查冲突。