【问题标题】:Compare lists to find common elements in python [duplicate]比较列表以查找python中的常见元素[重复]
【发布时间】:2012-11-22 12:40:45
【问题描述】:

可能重复:
Python - Intersection of two lists

我正在尝试比较两个列表,以找出它们共有的元素数量。

我遇到的主要问题是当任一列表包含重复元素时,例如

A = [1,1,1,1]   and  
B = [1,1,2,3]

使用代码

n = 0
for x in A:
   if x in B:
      n += 1
print n

给我n = 4 的输出,因为从技术上讲,A 的所有元素都在 B 中

我想获得n = 2 的输出,最好不使用集合,无论如何我可以调整我的代码,或者以新的方式思考问题来实现这一目标吗?

谢谢

【问题讨论】:

  • 是否有特别的理由避免使用集合?他们似乎提供了完美的解决方案:len(set(A)&set(B))
  • 不是特别的,只是修订表的问题,我们还没有真正使用过集合
  • 您确定您希望给出的示例的答案是 2,而不是 1?两个列表中只有一个值(数字 1)。如果集合是[1,2,3,3][1,1,2,3],您希望计数是多少?
  • 是的,在我给出的示例中,两个列表中都存在两个元素,而它们都是 1,它们是两个列表中都存在的两个元素。在您的示例中,我希望输出为 3,因为第一个列表中的 1、2 和 3 都存在于第二个列表中

标签: python


【解决方案1】:

尚不完全清楚您的规范是什么,但如果您想要B 中出现的A 中的元素数量,不考虑顺序,但考虑多重性,请使用collections.Counter

>>> from collections import Counter
>>> A = [1,1,1,1]
>>> B = [1,1,2,3]
>>> C = Counter(A) & Counter(B)
>>> sum(C.itervalues())
2
>>> list(C.elements())
[1, 1]

【讨论】:

  • 是的,这就是我想要的,谢谢
  • 这可能是性能最高的解决方案。我认为是 O(N)(其中 N 是 len(A)+len(B))。
  • @GarethRees 不知道,我给了它+1。这个问题是关于多重集的,而计数器是 python 中事实上的多重集容器。
【解决方案2】:

这是一种不使用集合的有效 (O(n logn)) 方法:

def count_common(a, b):
  ret = 0
  a = sorted(a)
  b = sorted(b)
  i = j = 0
  while i < len(a) and j < len(b):
    c = cmp(a[i], b[j])
    if c == 0:
      ret += 1
    if c <= 0:
      i += 1
    if c >= 0:
      j += 1
  return ret

print count_common([1,1,1,1], [1,1,2,3])

如果您的列表始终按您的示例进行排序,则可以放弃两个 sorted() 调用。这将给出一个O(n) 算法。

【讨论】:

  • 我在排序数组上测试了这个,没有 sorted() 调用,完全类型化并使用 Cython 编译,它比简单的 sorted(set(a) &amp; set(b)) 慢,即使有 > 1e10 个随机元素。另外后者不需要对初始列表进行排序。
【解决方案3】:

这是一种完全不同的思考问题的方式。

假设我有两个词,"hello""world"。为了找到共同的元素,我可以遍历"hello",给我['h', 'e', 'l', 'l', 'o']。对于列表中的每个元素,我将从第二个list(word) 中删除它。

  1. 'h'['w', 'o', 'r', 'l', 'd'] 中吗?没有。
  2. 'e'['w', 'o', 'r', 'l', 'd'] 中吗?没有。
  3. 'l'['w', 'o', 'r', 'l', 'd'] 中吗?是的!
  4. "world" 中删除它,给我['w', 'o', 'r', 'd']
  5. 'l'['w', 'o', 'r', 'd'] 中吗?没有。
  6. 'o'['w', 'o', 'r', 'd'] 中吗?
  7. 是的!删除它['w', 'o', 'r', 'd'],给我['w', 'r', 'd']

比较原始对象的长度(确保您保留了一个副本)和新生成的对象,您会看到差异为 2,表示 2 个常用字母。

【讨论】:

  • 这是一种非常好的和完全不同的解决方法,我想我会尝试在我的代码中使用它。非常感谢!
【解决方案4】:

所以你想让程序检查两个列表中是否只有相同索引处的元素相等?那将非常简单:只需遍历两个数组的长度(我认为应该具有相同的长度),例如使用变量 i,然后通过 A.index(i) 和 B 比较每个数组。 index(i) 函数。 如果你愿意,我可以发布代码。

如果这不是您想要做的,请务必让您的问题更清楚。

【讨论】:

  • 如果需要的话,我会使用zip 来组合列表,而不是在索引上循环。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2017-06-14
  • 2010-12-03
  • 2012-07-06
  • 2021-12-13
相关资源
最近更新 更多