我有一个清单:
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 :(得分: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
如果您的tol
为0.01
,那么round_digits
为1.因此,6.23234121
的{{1}}被编入索引seen
只有6.2
。当我们看到6.23246575
后,我们将其四舍五入到6.2
并在索引中查找,该索引应包含可能在我们查找的数字tol
内的所有数字。然后我们仍然需要检查这些数字的距离,但只检查该索引区中的极少数,而不是整个列表。
这种方法是O(n k),其中k是将落入一个这样的bin中的平均元素数。只有当k <&lt;&lt; n(通常是这样,但这取决于您使用的数字相对于tol
的分布)。请注意,它也使用的内存可能是另一种方法的两倍多,这可能是非常大的列表的问题。
另一种选择是先对列表进行排序;那么你只需要查看前面和后面的元素来检查冲突。