简体   繁体   English

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

[英]How to XOR two lists in Python?

I've got two lists, for example: 我有两个列表,例如:

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

If I want to create a third list that only contains elements NOT in both: 如果我想创建一个仅包含两个元素的第三个列表:

c = ['im','steve']

How do I do this if the order of the elements IS important? 如果元素的顺序很重要,我该怎么做? I know I can use sets but they keep throwing out the order of my lists. 我知道我可以使用套装,但他们不断抛弃我的清单。 I could use ' '.join(list) to convert them to strings but not sure how to do this operation in that format either. 我可以使用' '.join(list)将它们转换为字符串但不确定如何以该格式执行此操作。

You can concatenate the lists and use list comprehension: 您可以连接列表并使用列表理解:

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]

Output: 输出:

['im', 'steve']

Option 1: set method (recommended) 选项1:设定方法(推荐)

Sets have a symmetric_difference method that exclusively return elements from either a or b . 集合具有symmetric_difference方法,该方法专门从ab返回元素。 Order can be preserved with a list comprehension for a concatenated list a + b . 可以使用列表理解来保留顺序,用于连接列表a + b

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

Option 2: pathlib method 选项2: pathlib方法

For reference, another way to diff two lists might be with pathlib.Path.relative_to method: 作为参考,另一种pathlib.Path.relative_to两个列表的方法可能是使用pathlib.Path.relative_to方法:

import pathlib


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

Note: b is the longer list. 注意: b是较长的列表。 This option is potentially less efficient than a simple list comprehension. 此选项的效率可能低于简单列表推导。

Add two lists together and minus the intersection part if it shows in the new list. 如果在新列表中显示,则将两个列表一起添加并减去交叉部分。 Order is preserved. 订单保留。

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

You could also just create a function that filters elements from l1 that don't exist in l2 , and call it twice with the arguments flipped: 您还可以创建一个函数来过滤 l1中不存在于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']

If you don't wish to use filter() , a simple list comprehension like this also works: 如果你不想使用filter() ,这样的简单列表理解也有效:

[item for item in l1 if item not in l2]
a = ['hello','world']
b = ['hello','world','im','steve']
a = set(a)
b = set(b)
print(a.symmetric_difference(b))

This code print elements that are only in one of the tables. 此代码打印元素仅在其中一个表中。

Look here: https://learnpython.org/en/Sets 请看这里: https//learnpython.org/en/Sets

The question is not very clear, indeed, and probably you're good with @Ajax1234 's answer , but here's another "take" on it. 事实上,这个问题并不是很清楚,而且你可能对@ Ajax1234的答案很好,但这里有另一个“接受”。

If you wanna compare positions (kind of what a bit-wise XOR would do) you can do something like getting the shortest list, iterate checking position by position with the longest list (check the same position in the longest list matches the word in the shortest list) and then add the remainder (the " unwalked " part of the longest list). 如果你想比较位置(有点像XOR会做什么),你可以做一些事情,比如获得最短的列表,迭代按最长列表的位置检查位置(检查最长列表中的相同位置是否匹配最短列表)然后添加余数(最长列表中的“未行走 ”部分)。 Something like the following: 类似于以下内容:

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

However, then you have the problem of what to do if the same positions don't match. 但是,如果相同的位置不匹配,那么您有问题该怎么办。 I mean... What to do in that case? 我的意思是......那个案子该怎么办? In the code above, I just added both entries to the results list, which means for the following inputs: 在上面的代码中,我只是将两个条目添加到results列表中,这意味着对于以下输入:

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

would output: 输出:

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

(notice both foo from list a and world from list b have been added) (注意列表a foo和列表b world都已添加)

Using standard for loop to check for items not in one or the other list (may be more understandable than list comprehension): 使用标准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)

Output: 输出:

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

I recommend, using ^ operator with sets, like set(a) ^ set(b) , Example (demo): 我建议,使用带有集合的^运算符,如set(a) ^ set(b) ,Example(demo):

>>> 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 https://docs.python.org/2/library/stdtypes.html#frozenset.symmetric_difference

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM