我有两个列表list1
和list2
。我在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
那么,有没有简单的方法在两个列表之间使用公共元素并保留元素的顺序?
答案 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)]