如何在Python中对两个列表进行异或操作?

9

我有两个列表,例如:

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

如果我想创建一个第三个列表,仅包含不在两个列表中的元素:
c = ['im','steve']

如果元素的顺序很重要,我该怎么办?我知道可以使用集合,但它们会打乱我的列表顺序。我可以使用' '.join(list)将它们转换为字符串,但不确定如何在该格式中执行此操作。

4
如果顺序很重要,当列表 a 是例如 ['hello', 'the', 'world']['world', 'hello'] 时,你该怎么办?如果它是 ['world', 'hello', 'world'] 呢?如果其中包含 'steve',那么它出现的位置是否重要? - torek
8个回答

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

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

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']

10

选项1:使用set方法(推荐)

集合有一个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çois Fabre
@Jean-FrançoisFabre 确认。帖子已更新。谢谢。 - pylang

5
将两个列表合并,并从新列表中减去交集部分。顺序保持不变。
c = a + b
for v in set(a).intersection(set(b)):
    while v in c:
        c.remove(v)

1
从问题来看:“如果元素的顺序很重要,我该如何做到这一点?” - viraptor
1
这个忽略了重复项。例如 a=[1, 1, 2, 3] ; b=[1, 2] 将返回 c=[3, 1] - viraptor
2
不要太在意负评。如果你有一个新的好答案,你总是可以删除错误的答案。(甚至有一个徽章为此)另一方面,如果答案不正确,通过投票标记它是好的。 - viraptor
1
@Tai,这个网站上的负评是不可避免的,即使你给出了一个好答案。最好的办法是不断编辑你的回答直到正确,并希望一切顺利。不要太过于认真对待这些负评。 - RoadRunner
谢谢你们告诉我这个。我很感激。很抱歉我一直在回避它。我会放轻松的。这是我第二次被踩了。还不太习惯。@RoadRunner - Tai
显示剩余2条评论

3
你也可以创建一个函数,过滤掉在l2中不存在的元素,然后将参数反转后调用该函数两次:
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]

3
a = ['hello','world']
b = ['hello','world','im','steve']
a = set(a)
b = set(b)
print(a.symmetric_difference(b))

这段代码打印出只存在于其中一个表格中的元素。
请查看: https://learnpython.org/en/Sets

1
集合不维护顺序。 - pylang

2
这个问题并不是非常清晰,也许您已经通过@Ajax1234的答案解决了它,但这里有另一种方式。
如果你想比较位置(有点像按位异或),可以做以下操作:获取最短列表,迭代检查最长列表中的每个位置是否与最短列表中的单词匹配(检查最长列表中相同位置是否匹配最短列表中的单词),然后添加剩余部分(最长列表中未遍历的部分)。类似以下内容:
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添加。

1
如果您使用 zip,则无需检查列表的大小,还可以使用 max 选择最长的列表,或者使用 sorted 同时完成两个操作。 - Copperfield

2

使用标准的 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" 是从哪里来的? - pylang
我已将我的列表添加在上方。 - rnso

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接