【问题标题】:comparing a list of lists with itself将列表列表与其自身进行比较
【发布时间】:2016-05-03 15:27:00
【问题描述】:

我已经在一定程度上解决了这个问题,我只是想找出一种更有效的方法来解决这个问题。我有一个大列表,我正在尝试将大列表中的每个列表相互比较。

如何避免重复比较,比较已经比较过的列表?

例如:big_list[0] 已与 big_list[20] 进行比较,因此没有理由在循环稍后将 big_list[20] 与 big_list[0] 进行比较。

        big_list= [[0.12, 0.939, -0.321, 6.342], [0.12, 0.939, -0.321,6.342], [0.0, 1.0, -0.0, -5.166], [0.0, 1.0, 0.0, -5.166], [0.0, 1.0, -0.0, -5.166], [-0.0, 1.0, 0.0, -5.166], [0.0, 1.0, 0.0, -5.166], [0.0, 1.0, 0.0, -5.166], [0.0,1.0, -0.0, -5.166], [0.0, 1.0, 0.0, -5.166], [-0.0, 1.0, -0.0, -5.166], [-0.0, 1.0, 0.0, -5.166], [-0.12, 0.939, 0.321, 0.282], [-0.12, 0.939, 0.321, 0.282], [0.12, 0.939, 0.321, -17.782], [0.12, 0.939, 0.321, -17.782], [-0.0, 1.0, 0.0, 0.834], [0.0, 1.0, 0.0, 0.834], [0.0, 1.0, 0.0, 0.834], [0.0, 1.0, 0.0, 0.834], [-0.12, 0.939, -0.321, 24.406], [-0.12, 0.939, -0.321, 24.406], [0.0, 0.874, -0.486, 21.883], [0.0, 0.874, -0.486, 21.883], [0.0, 0.874, 0.486, -14.598], [0.0, 0.874, 0.486, -14.598]]

        for j in range(len(big_list)):
            for k in range(len(big_list)):
                if j!=k: 

                   result=math.sqrt(sum([(a-b)**2 for a,b in zip(big_list[j],big_list[k])])))

以前,我通过设置特定容差并将每个结果附加到新列表来解决此问题,但我正在尝试提出一种更有效的方法来执行此操作。最终,big_list 可能会拥有超过 100 万个列表

if result<=rel_tol and big_list[k] not in new_list:
    new_list.append(big_list[k])

【问题讨论】:

  • 你为什么要把它们相互比较?如果要对列表进行排序,您可以指定 key,它将任何逻辑应用于每个元素并进行比较。
  • 列表是否可以间接包含自身?
  • 例如a = []; a.extend([a,(a,)])

标签: python algorithm list data-structures


【解决方案1】:

而不是做:

for j in range(len(big_list)):
        for k in range(len(big_list)):

这样做(注意j+1):

for j in range(len(big_list)):
        for k in range(j+1, len(big_list)):

这样,您的内部循环将跳过您已经查看过的所有索引,避免重复比较。

【讨论】:

  • 谢谢,最终目标是避免重复比较
【解决方案2】:

您可以将它们转换为元组并使用Counter 来查看有多少实例,而不是使用两个for 循环将列表相互比较。然后,您可以遍历列表并选择具有多个实例的每个子列表的第一个匹配项。

from collections import Counter

c = Counter(tuple(l) for l in big_list)
new_list = []
for l in big_list:
    t = tuple(l)
    if c[t] > 1:
        new_list.append(l)
        c[t] = 0

这具有 O(n) 时间复杂度,并且会产生与原始代码相同的顺序。

【讨论】:

  • 谢谢!我喜欢你如何重新构建我试图回答的问题。
【解决方案3】:

@Justin 的回答也是我的第一个想法,但经过反思,我认为这对于真正的big_lists 来说并不是最有效的。相反,我会使用set()s of tuples:

tupled_set = set([tuple(i) for i in big_list])
new_list_of_tuples = list(tupled_set)

仅使用内置迭代更短更快。现在当然,如果您需要返回列表(出于某种原因需要可变子列表),那么性能增益可能会丢失(不确定,需要进行基准测试),但可读性不是:

list_of_lists = [list(i) for i in new_list_of_tuples]

干杯

【讨论】:

  • 这不一定会导致与原始代码相同的顺序,但这可能无关紧要,具体取决于上下文。
  • @niemmi 有效积分!我不得不用谷歌搜索 Python 中集合的稳定性,并在今天学到了一些新东西:stackoverflow.com/questions/3812429/is-pythons-set-stable Python 集合实际上是稳定的(未来无法保证,它们恰好在今天的 CPython 实现中就是这样)。
  • 如果我理解正确,那就是在一个未更改的集合上进行多次迭代,以相同的顺序返回项目。该顺序不一定与插入顺序相同。例如,我在我的机器上关注:list(set(range(5, 0, -1))) -> [1, 2, 3, 4, 5].
  • 再次完全正确,我误解了示例代码。干杯!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2010-12-25
  • 1970-01-01
  • 1970-01-01
  • 2023-03-15
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多