【问题标题】:A list contains another list with repetition一个列表包含另一个重复的列表
【发布时间】:2013-12-15 11:02:27
【问题描述】:

我需要检查一个列表是否包含 python 中另一个列表的每个元素。不完全是集合操作,因为在集合中考虑了不同的值。我该怎么做?

示例: a 是较大的列表,b 是较小的集合

a = [1, 1, 2, 4], b = [1, 2, 3] -> False
a = [1, 1, 2, 3], b = [1, 2, 3] -> True
a = [1, 2, 4], b = [1, 2, 1] -> False // Because b has two 1s but a has only one.

请您仔细查看第三种情况。

[N. B.] 我确切地知道如何通过哈希映射来完成。但我想要不那么笨重的东西。

【问题讨论】:

  • @Blender 不幸的是,这不起作用。 Counter( [1, 1] ) <= Counter( [1, 2] ) 计算结果为 True。大概是因为Counter.__sub__ 只保留正数。
  • @svk:啊,你是对的。我认为有一些重载的运算符可以让你这样做,但事实并非如此。
  • multiset 的任何选项都可用?

标签: python list contains


【解决方案1】:

Counter 的简单单行代码

def isin(a, b): return not (Counter(b) - Counter(a))

演示:

>>> isin([1, 1, 2, 4], [1, 2, 3])
False
>>> isin([1, 1, 2, 3], [1, 2, 3])
True
>>> isin([1, 1, 2, 4], [1, 2, 1])
True
>>> isin([1, 2, 4], [1, 2, 1])
False

【讨论】:

  • +1 如此简单、优雅,现在我明白为什么不需要>=
【解决方案2】:
from collections import Counter

def is_contained(a,b):
    aCount = Counter(a)
    bCount = Counter(b)
    return all(aCount[x] >= bCount[x] for x in bCount)



>>> is_contained([1, 1, 2, 4],[1, 2, 3])
False
>>> is_contained([1, 1, 2, 3], [1, 2, 3])
True
>>> is_contained([1, 2, 4],  [1, 2, 1])
False

【讨论】:

  • 会有多糟糕?关于时间复杂度的任何想法?
  • 到目前为止一切顺利。针对某些情况进行了测试。如果问题再次发生,我会通知您。顺便说一句,任何多组选项都可用?
  • 如果性能是一个问题,也许这会更快all(aCount[x] >= bcountx for x, bcountx in bCount.iteritems() )。 +1 使用计数器...
  • @Md.TaufiqueHussain 计数器解决方案是 O(n),这在这种情况下是最好的。
  • @DhruvPathak 我对 Counter-Class 做了一些进一步的研究,它提供了交叉点。所以你可以在你的函数中使用return aCount & bCount == bCount
【解决方案3】:
from collections import Counter

def is_contained(a, b):
    aCount = Counter(a)
    bCount = Counter(b)
    # think of it as aCount >= bCount in set-operations
    return aCount & bCount == bCount

【讨论】:

  • 很优雅,我喜欢。
  • 它有效,但我是 python 新手。所以请善意地解释一下。顺便说一句,这里的复杂性是什么?看起来像 O(1) 但这取决于 Counter() 并且我不知道它到底是做什么的。
  • 您可以在Counter-Documentation. 获得更多信息,该行首先构建两个计数器的交集,这意味着对于两个计数器中的每个计数键,它的出现次数最少。如果 a 包含 b,则此 Counter-intersection(或称其为最小值)必须为 bCount。将其与 set-statement 进行比较:setA & setB == setBsetB <= setA 的含义相同。 Counter 没有正确的<=-实现,所以我不得不采取其他方法。
  • @koffein 计数器可以添加,见我的回答中的例子
  • @alko 是的,我明白了。我想过减去aCount - bCount,然后寻找负“值”,但我没有想到bCount - aCount……花了一些时间思考,但没有想到最简单的……
【解决方案4】:

我问了一个类似的问题,这个问题在结束时提到了这个问题。我对这些答案的问题是它们都从列表中创建了一个 Counter 对象。除非我误解了某些东西,否则这实际上是在创建完整列表和子列表的副本。如果两者都很小,这并不重要,但如果您正在处理大型列表,那将是低效的。我选择了这个:

def is_valid_sub(full_list, sub_list):
    matched = []
    for sub_item in sub_sublist:
        for indx, full_item in enumerate(full_list):
            if sub_item == full_item and indx not in matched:
                matched.append(indx)
                break
    return len(matched) == len(sub_list)

编辑:添加更有意义的变量名

【讨论】:

  • 你应该给你的变量起有意义的名字,否则就不太清楚了......
【解决方案5】:

定义包含(a,b): 对于 set(a) 中的项目: 如果集合(b)中的项目: print '某事或做某事'

【讨论】:

  • 看我提到set操作不是我想要的。
猜你喜欢
  • 1970-01-01
  • 2021-04-14
  • 1970-01-01
  • 1970-01-01
  • 2012-05-31
  • 2021-08-21
  • 1970-01-01
  • 1970-01-01
  • 2015-02-08
相关资源
最近更新 更多