简体   繁体   English

两个列表之间的公共元素,并保留两个列表中元素的顺序

[英]Common elements between two lists and preserving the order of elements in the two lists

I have two lists list1 and list2 . 我有两个列表list1list2 I've found on stackoverflow a very simple method to get the common elements in this two lists as follows result = list(set(list1) & set(list2)) . 我在stackoverflow上找到了一个非常简单的方法来获取这两个列表中的公共元素,如下所示result = list(set(list1) & set(list2)) Unfortunately, with this, the order of elements in the resulting list, is not preserved. 不幸的是,使用它,不保留结果列表中元素的顺序。

For instance: 例如:

list1 = ['a', 'e', 't', 'b', 'c']
list2 = ['e', 'b', 'a', 'c', 'n', 's']

I want the result (common elements) to be ['e', 'a', 'b', 'c'] in this order. 我希望结果(共同元素)按此顺序为['e', 'a', 'b', 'c'] Because, for instance, 'e' is in list1 and in list2 and is in position 2 in list1 and position 1 in list2, while 'a' is in list1 and in list2 and is in position 1 in list1 and position 3 in list2, so 'e' is before 'a' since 2+1 < 1+3. 例如,因为'e'位于list1和list2中,位于list1中的位置2和list2中的位置1,而'a'位于list1和list2中,位于list1中的位置1和list2中的位置3,所以'e'在'a'之前,因为2 + 1 <1 + 3。

So, is there any simple way to have the common elements between two lists and preserving the order of elements ? 那么,有没有简单的方法在两个列表之间使用公共元素并保留元素的顺序?

list1 = ['a', 'e', 't', 'b', 'c']
list2 = ['e', 'b', 'a', 'c', 'n', 's']

weights = defaultdict(int)

for i, e in enumerate(list1):
   weights[e] += i

for i, e in enumerate(list2):
   weights[e] += i

>>> result = sorted(set(list1) & set(list2), key=lambda i: weights[i])
>>> result
['e', 'a', 'b', 'c']

You could use a list comprehension to filter all elements from list1 that don't also belong to list2 : 您可以使用列表推导来过滤list1中不属于list2所有元素:

list1 = ['a', 'e', 't', 'b', 'c']
list2 = ['e', 'b', 'a', 'c', 'n', 's']

result = [item for item in list1 if item in list2]
print result

Result: 结果:

['a', 'e', 'b', 'c']

Although this does not conform to the desired result in your main post, from your follow-up comment it seems like this is an acceptable result. 虽然这不符合您主要帖子中的预期结果,但从您的后续评论来看,这似乎是可接受的结果。


You could also continue using the set approach, and then sort the results after the fact using the positioning algorithm you described: 您还可以继续使用set方法,然后使用您描述的定位算法对结果进行排序:

list1 = ['a', 'e', 't', 'b', 'c']
list2 = ['e', 'b', 'a', 'c', 'n', 's']

items = set(list1) & set(list2)
result = sorted(items, key=lambda element: list1.index(element) + list2.index(element))

print result

Result: 结果:

['e', 'a', 'b', 'c']

You can preserve the order of one list like this, by making only one of them a set: 您可以通过只设置其中一个列表来保留这样一个列表的顺序:

list1 = ['a', 'e', 't', 'b', 'c']
list2 = ['e', 'b', 'a', 'c', 'n', 's'] 

slist1 = set(list1)
slist2 = set(list2)

# list1 determines the ordering
olist1 = [x for x in list1 if x in slist2]

# list2 determines the ordering
olist2 = [x for x in list2 if x in slist1]

Basically, you iterate over one list, and check each item to see if it's in the other. 基本上,您迭代一个列表,并检查每个项目以查看它是否在另一个项目中。 This ensures that your final list is in the same order as the original, but also that it only includes entries in both lists. 这可以确保您的最终列表与原始列表的顺序相同,但它也只包含两个列表中的条目。

Using sets speeds up the inclusion checking considerably. 使用集合大大加快了包含检查。

If you want to do anything more complex than this (make final ordering dependent on indexes in both lists, for instance), then you'd need to be more specific on those details. 如果你想做比这更复杂的事情(例如,最终的排序取决于两个列表中的索引),那么你需要更具体地了解这些细节。

edit: OK, you did post more details about what you want to do. 编辑:好的,您确实发布了有关您要执行的操作的更多详细信息。 Don't know if it's the fastest , but you can do something like this to get the indices: 不知道它是否是最快的 ,但你可以做这样的事情来获得指数:

list1_offsets = dict(x[::-1] for x in enumerate(list1))
list2_offsets = dict(x[::-1] for x in enumerate(list2))

total_list = slist1 & slist2

total_offset = [(x, list1_offsets[x] + list2_offsets[x]) for x in total_list]

final_list = [x[0] for x in sorted(total_offset, key=itemgetter(1))]

In this case, the output was the expected ['e', 'a', 'b', 'c'] . 在这种情况下,输出是预期的['e', 'a', 'b', 'c']

Your ordering function seems pretty odd but ok. 你的订购功能看起来很奇怪,但还可以。 You need to find the intersection and sort it by your ordering function basically. 您需要找到交叉点并基本按您的订购功能对其进行排序。

order_function = lambda val: list1.index(val) + list2.index(val)
common = set(list1) & set(list2)
indexed = [(order_function(v), v) for v in common]
return [x[1] for x in sorted(indexed)]

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

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