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

时间:2014-01-10 13:38:38

标签: python list

我有两个列表list1list2。我在stackoverflow上发现了一个非常简单的方法来获取这两个列表中的公共元素,如下所示result = list(set(list1) & set(list2))。不幸的是,使用它,结果列表中元素的顺序不会被保留。

例如:

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

我希望结果(公共元素)按此顺序为['e', 'a', 'b', 'c']。例如,因为'e'位于list1和list2中,位于list1中的位置2和list2中的位置1,而'a'位于list1和list2中,位于list1中的位置1和list2中的位置3,所以'e'在'a'之前,因为2 + 1< 1 + 3

那么,有没有简单的方法在两个列表之间使用公共元素并保留元素的顺序?

4 个答案:

答案 0 :(得分:4)

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

答案 1 :(得分:3)

您可以使用列表推导来过滤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

结果:

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

虽然这不符合您主要帖子中的预期结果,但从您的后续评论来看,这似乎是可接受的结果。


您还可以继续使用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

结果:

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

答案 2 :(得分:1)

您可以通过只设置其中一个列表来保留这样一个列表的顺序:

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]

基本上,您迭代一个列表,并检查每个项目以查看它是否在另一个列表中。这可确保您的最终列表与原始列表的顺序相同,但也只包括两个列表中的条目。

使用集合大大加快了包含检查。

如果你想做比这更复杂的事情(例如,最终的排序取决于两个列表中的索引),那么你需要更具体地说明这些细节。

编辑:好的,您确实发布了有关您要执行的操作的更多详细信息。 不知道它是最快的,但你可以做这样的事情来获得指数:

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

在这种情况下,输出是预期的['e', 'a', 'b', 'c']

答案 3 :(得分:0)

你的订购功能看起来很奇怪但还可以。您需要找到交叉点并基本按您的订购功能对其进行排序。

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