【问题标题】:comparing contents of 2 lists of lists比较 2 个列表的内容
【发布时间】:2013-10-10 23:45:22
【问题描述】:

这是我遇到问题的任务:

给定 2 个列表,将它们过滤到只有没有共同点的项目。例如。如果内部列表相同,则将它们过滤掉。如果内部列表至少有一个共同点,也将它们过滤掉。

注意:只有一层嵌套。内部列表仅由字符串组成。我有一个可行的解决方案,但它非常混乱。寻求反馈以改进:

首先我过滤掉两个列表中的完全匹配:

l3 = filter(lambda x: x not in l2, l1)
l4 = filter(lambda x: x not in l1, l2)

我最终得到了 2 个不完全相同项目的列表。现在我想遍历内部列表,并摆脱与另一个内部列表共享项目的任何列表。

我在做:

    for i in l3:
        for j in i:
            for k in l4:
                if j in k:
                    print j, k
                    removel3.append(tuple(i))
                    removel4.append(tuple(k))
    for i in l4:
        for j in i:
            for k in l3:
                if j in k:
                    removel3.append(tuple(k))
                    removel4.append(tuple(i))
    for i in list(set(removel3)):
        l3.remove(list(i))
    for i in list(set(removel4)):
        l4.remove(list(i))

(构建要从列表中删除的单独列表,因为直接在迭代循环中删除会弄乱列表索引并跳过项目。必须有更好的方法,但我不知道。)

但是是的。它完成了工作,但是从元组到集合再到列表再到更多元组……听起来很不合 Python。 :) 很高兴看到任何反馈!

编辑:

示例输入:

l1 = [['A', 'B', 'C'], ['D', 'E'], ['F', 'G', 'H']]
l2 = [['A', 'B', 'C'], ['D', 'I'], ['K', 'L', 'M']]

经过上述所有转换,最终得到:

>>> l3
[['F', 'G', 'H']]
>>> l4
[['K', 'L', 'M']]

【问题讨论】:

  • 你能给出一个示例输入和预期输出吗?
  • 向我们展示一些数据:样本输入和期望的输出。
  • @FMc:伟大的思想都一样
  • 你去,对不起:)

标签: python list


【解决方案1】:

我不确定我是否理解你,但我会试一试。

# first, get all elements from each list as a flat set.
import itertools
set1 = set(itertools.chain.from_iterable(list1))
set2 = set(itertools.chain.from_iterable(list2))

#Now, figure out which elements they have in common
common_elements = set1 & set2

#Now eliminate inner lists which have elements in the common set
new_list1 = [lst for lst in list1 if not any(x in common_elements for x in lst)]
new_list2 = [lst for lst in list2 if not any(x in common_elements for x in lst)]

请注意,我可以这样做,因为子列表包含可散列的对象。

【讨论】:

  • if not set(lst).intersection(common_elements) 呢?但是是的,可能比我的解决方案更有效......但我认为它们都有效:)
  • @JoranBeasley -- if not common_elements.intersection(lst) 会更有效率,我想使用它。使用any 允许短路,因此在算法上会更好一些。当橡胶遇到道路时,我们需要用真实数据进行真实测试,看看哪个实际上更快——set.intersection 的实现可能会击败any 的短路优势。
  • 这也有效,但 Joran 的回答似乎更好,至少在美学上 :) 谢谢!
【解决方案2】:

我认为这样的过滤器就是你想要的

filter(lambda sublist:not any(set(sublist).intersection(x) for x in list2),list1)

【讨论】:

  • 这只返回第一个列表。也许你打算这样做两次?
  • 是的,必须有一个带 l2、l1 和另一个带 l1、l2。但它确实完成了工作。我对 .intersection() 没有太多经验,需要研究一下。非常感谢!
  • 这将是更 Pythonic 和更高效的列表理解:[sublist for sublist in list1 if not any(set(sublist).intersection(x) for x in list2]
  • FWIW,这会重新创建很多集合。你最好提前做set2 = map(set, list2),然后在any生成器中使用set2而不是list2
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-01-22
  • 2018-03-08
  • 1970-01-01
  • 1970-01-01
  • 2022-06-26
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多