【问题标题】:How to XOR two lists in Python? [duplicate]如何在 Python 中对两个列表进行异或? [复制]
【发布时间】:2017-12-27 01:20:54
【问题描述】:

我有两个列表,例如:

a = ['hello','world']
b = ['hello','world','im','steve']

如果我想创建第三个列表,该列表只包含两者中不包含的元素:

c = ['im','steve']

如果元素的顺序很重要,我该怎么做?我知道我可以使用集合,但他们总是把我的列表顺序扔掉。我可以使用' '.join(list) 将它们转换为字符串,但也不确定如何以该格式执行此操作。

【问题讨论】:

  • 如果订单很重要,当a['hello', 'the', 'world']['world', 'hello']时,你会怎么做?如果是['world', 'hello', 'world'] 怎么办?如果它在某处包含'steve' 怎么办,在哪里重要吗?

标签: python python-3.x


【解决方案1】:

选项一:设置方法(推荐)

集合有一个symmetric_difference 方法,它专门从ab 返回元素。可以使用串联列表a + b 的列表推导来保留顺序。

comp = set(a).symmetric_difference(b)
[x for x in a + b if x in comp]
# ['im', 'steve']

选项 2:pathlib 方法

作为参考,区分两个列表的另一种方法可能是使用pathlib.Path.relative_to 方法:

import pathlib


p = pathlib.Path(*b)
r = p.relative_to(*a)
list(r.parts)
# ['im', 'steve']

注意:b 是较长的列表。此选项的效率可能低于简单的列表推导。

【讨论】:

  • 你必须预先计算 set(a).symmetric_difference(b) 否则会很慢。
  • @Jean-FrançoisFabre 已确认。更新帖子。谢谢。
【解决方案2】:

您可以连接列表并使用列表推导:

a = ['hello','world']
b = ['hello','world','im','steve']
final_vals = [i for i in a+b if i not in a or i not in b]

输出:

['im', 'steve']

【讨论】:

    【解决方案3】:

    将两个列表相加并减去交叉部分(如果它显示在新列表中)。订单被保留。

    c = a + b
    for v in set(a).intersection(set(b)):
        while v in c:
            c.remove(v)
    

    【讨论】:

    • 来自问题:“如果元素的顺序很重要,我该怎么做?”
    • 现在将进行编辑以适应它。您可以删除反对票吗? @viraptor
    • 这忽略了重复。例如a=[1, 1, 2, 3] ; b=[1, 2] 将返回c=[3, 1]
    • 不要太担心否决票。如果您有一个新的好答案,您可以随时删除错误的答案。 (甚至还有一个badge)另一方面,如果答案不正确,最好通过投票来标记它。
    • @Tai,即使您做出了很好的回答,在这个网站上也不可避免地会被否决。最好的办法是编辑你的答案,直到它正确,并希望最好。不要太认真。
    【解决方案4】:

    您也可以只创建一个函数,其中包含 l1 中不存在于 l2 中的 filters 元素,并在翻转参数的情况下调用它两次:

    a = ['hello','world', 'foo']
    b = ['hello','world','im','steve']
    
    def difference(l1, l2):
        return list(filter(lambda x: x not in l2, l1))
    
    print(difference(a, b) + difference(b, a))
    # ['foo', 'im', 'steve']
    

    如果您不想使用filter(),也可以使用这样的简单列表推导:

    [item for item in l1 if item not in l2]
    

    【讨论】:

      【解决方案5】:
      a = ['hello','world']
      b = ['hello','world','im','steve']
      a = set(a)
      b = set(b)
      print(a.symmetric_difference(b))
      

      此代码打印仅在其中一个表中的元素。

      看这里: https://learnpython.org/en/Sets

      【讨论】:

      • 集合不保持顺序。
      【解决方案6】:

      确实,这个问题不是很清楚,可能你对@Ajax1234 的answer 很熟悉,但这里有另一个“看法”。

      如果你想比较位置(有点 XOR 会做的事情),你可以做一些事情,比如获取最短列表,逐个位置迭代检查最长列表的位置(检查最长列表中的相同位置是否匹配最短列表中的单词),然后添加剩余部分(最长列表的“unwalked”部分)。类似于以下内容:

      a = ['hello', 'world']
      b = ['hello', 'world', 'im', 'steve']
      
      min_list = a if len(a) < len(b) else b
      max_list = b if len(b) > len(a) else a
      
      results = []
      for i, item in enumerate(min_list):
          # Iterate through the shortest list to avoid IndexError(s)
          if min_list[i] != max_list[i]:
              results.append(min_list[i])
              results.append(max_list[i])
      results.extend(max_list[i + 1:])
      print(results)
      # Prints: ['im', 'steve']
      

      但是,如果相同的位置不匹配,您会遇到问题。我的意思是……在那种情况下该怎么办?在上面的代码中,我只是将两个条目添加到 results 列表中,这意味着以下输入:

      a = ['hello', 'foo']
      b = ['hello', 'world', 'im', 'steve']
      

      会输出:

      >>> ['foo', 'world', 'im', 'steve']
      

      (注意列表a 中的foo 和列表b 中的world 均已添加)

      【讨论】:

      • 如果你使用zip你不需要检查列表的大小,你也可以使用max来选择最长的列表,或者同时使用sorted
      【解决方案7】:

      使用标准 for 循环检查不在一个或另一个列表中的项目(可能比列表理解更容易理解):

      a = ['hello','world', 'foo']
      b = ['hello','world','im','steve']
      c = a+b
      ans = []
      for i in c:
          if i not in a or i not in b:
              ans.append(i)
      print(ans)
      

      输出:

      ['foo', 'im', 'steve']
      

      【讨论】:

      • “foo”在你的输出中来自哪里?
      • 我已经在上面添加了我的列表。
      【解决方案8】:

      我建议使用带有集合的^ 运算符,例如set(a) ^ set(b),示例(演示):

      >>> a = ['hello','world']
      >>> b = ['hello','world','im','steve']
      >>> set(a) ^ set(b)
      {'steve', 'im'}
      >>> sorted(set(a) ^ set(b),key=max([a,b],key=len).index)
      ['im', 'steve']
      >>> 
      

      https://docs.python.org/2/library/stdtypes.html#frozenset.symmetric_difference

      【讨论】:

        猜你喜欢
        • 2016-11-07
        • 2013-10-29
        • 2014-05-09
        • 1970-01-01
        • 2013-12-06
        • 2019-08-01
        • 2013-06-27
        • 2018-02-16
        相关资源
        最近更新 更多