【问题标题】:How can I remove similar but not duplicate items from a list?如何从列表中删除相似但不重复的项目?
【发布时间】:2013-02-07 00:03:28
【问题描述】:

我有一个清单:

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, 0.005, 0.01, 0.015, 0.02]返回什么?每个元素都有另一个元素在它的 0.01 以内。

标签: list python-3.x


【解决方案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

在三元素列表上,这非常好。但是,如果您想在 300 万个元素的列表上执行此操作,那将不会削减它。让我们尝试一些不同的东西:

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 是落在一个这样的 bin 内的平均元素数。仅当 k tol 的分布)。请注意,它使用的内存可能是其他方法的两倍多,这对于非常大的列表可能是个问题。


另一种选择是先对列表进行排序;那么您只需查看前面和后面的元素即可检查是否存在冲突。

【讨论】:

    猜你喜欢
    • 2019-03-22
    • 2021-03-15
    • 2023-01-09
    • 1970-01-01
    • 2018-06-02
    • 1970-01-01
    • 1970-01-01
    • 2020-12-05
    • 2018-05-15
    相关资源
    最近更新 更多