【问题标题】:Finding intersection of two lists of strings in python在python中查找两个字符串列表的交集
【发布时间】:2015-02-24 08:48:30
【问题描述】:

我经历过Find intersection of two lists?Intersection of Two Lists Of StringsGetting intersection of two lists in python。但是,我无法解决使用 Python 查找两个字符串列表之间的交集的问题。

我有两个变量。

A = [['11@N3'], ['23@N0'], ['62@N0'], ['99@N0'], ['47@N7']]

B  = [['23@N0'], ['12@N1']]

如何找到 '23@N0' 是 A 和 B 的一部分?

我尝试使用 http://www.saltycrane.com/blog/2008/01/how-to-find-intersection-and-union-of/ 中提到的 intersect(a,b) 但是,当我尝试将 A 转换为集合时,它会引发错误:

File "<stdin>", line 1, in <module> TypeError: unhashable type: 'list'

为了将其转换为集合,我使用了TypeError: unhashable type: 'list' when using built-in set function 中的方法,其中列表可以使用

result = sorted(set(map(tuple, A)), reverse=True)

变成一个元组,然后这个元组可以转换成一个集合。但是,这会返回一个空集作为交集。

你能帮我找到路口吗?

【问题讨论】:

  • 交叉大量数据的最快方法是使用 Python 集。 Python 集是散列映射,因此它们需要散列。您的问题来自将字符串包装到列表中。列表是可变对象,这就是为什么它们不能被散列,而字符串是不可变的,可以。
  • 每个列表中有一个字符串有什么原因吗?
  • 这是我的数据集,不是我生成的,是从别人那里借来的。
  • @SharathChandra:“借来的”是什么意思?您是否从文件中读取过它?什么格式?

标签: python string list set intersection


【解决方案1】:

您可以使用compiler.ast 模块的flatten 函数来展平您的子列表,然后像这样应用设置交集

from compiler.ast import flatten

A=[['11@N3'], ['23@N0'], ['62@N0'], ['99@N0'], ['47@N7']]
B=[['23@N0'], ['12@N1']]

a = flatten(A)
b = flatten(B)
common_elements = list(set(a).intersection(set(b)))
common_elements
['23@N0']

【讨论】:

  • compiler.ast 仅适用于 python 2;建议使用 itertools.chain
  • 同意你的观点,但是如果输入列表是这样的 A= ['11@N3', ['23@N0']] ,那么应用 itertools.chain 不会真正使列表变平。 list(itertools.chain(*A)) 之后的结果列表将是 ['1', '1', '@', 'N', '3', '23@N0']。
  • 也是如此;我们真正需要的是一个能够理解字符串、字节的flatten itertool。
  • @AnttiHaapala:也许,你正在寻找Flatten (an irregular) list of lists in Python
  • 不需要回答这个问题,除了许多答案在 3 中也不起作用。我的意思是,它应该是用 C 编写的核心。
【解决方案2】:

问题在于您的列表包含子列表,因此它们无法转换为集合。试试这个:

A=[['11@N3'], ['23@N0'], ['62@N0'], ['99@N0'], ['47@N7']]
B=[['23@N0'], ['12@N1']]

C = [item for sublist in A for item in sublist]
D = [item for sublist in B for item in sublist]

print set(C).intersection(set(D))

【讨论】:

    【解决方案3】:

    你的数据结构有点奇怪,因为它是一个单元素的字符串列表;您想将其简化为字符串列表,然后您可以应用以前的解决方案:

    因此列表如下:

    B = [['23@N0'], ['12@N1']]
    

    可以转换为遍历'23@N0', '12@N1'的迭代器

    itertools.chain(*),因此我们有简单的oneliner:

    >>> set(chain(*A)).intersection(chain(*B))
    {'23@N0'}
    

    【讨论】:

    • 如果 A 和 B 在最后一个语句中颠倒,这似乎确实有效。也就是说,如果我们尝试 set(B).intersection(A),它会产生一个空集。
    【解决方案4】:

    如果你必须把它放在幸运饼干上:

    set(i[0] for i in A).intersection(set(i[0] for i in B))
    

    【讨论】:

      【解决方案5】:

      您有两个列表,每个列表都有一个项目。为了将其转换为集合,您必须将其设为字符串列表:

      set_a = set([i[0] for i in A])
      set_b = set([i[0] for i in B])
      

      现在你可以得到路口了:

      set_a.intersection(set_b)
      

      【讨论】:

      • 你不需要在[]里面():set(x[0] for x in A) &amp; set(x[0] for x in B)
      【解决方案6】:
      A=[['11@N3'], ['23@N0'], ['62@N0'], ['99@N0'], ['47@N7']]
      A=[a[0] for a in A]
      B=[['23@N0'], ['12@N1']]
      B=[b[0] for b in B]
      print set.intersection(set(A),set(B))
      

      输出:set(['23@N0'])

      如果您的每个列表都只有 1 元素的子列表,您可以试试这个。

      【讨论】:

        【解决方案7】:

        我的偏好是使用标准库中的itertools.chain

        from itertools import chain
        
        A = [['11@N3'], ['23@N0'], ['62@N0'], ['99@N0'], ['47@N7']]
        
        B = [['23@N0'], ['12@N1']]
        
        set(chain(*A)) & set(chain(*B))
        
        # {'23@N0'}
        

        【讨论】:

          猜你喜欢
          • 2018-09-22
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2021-10-12
          相关资源
          最近更新 更多