Python中的列表匹配:获取一个子列表在更大列表中的索引。

9

对于两个列表,

a = [1, 2, 9, 3, 8, ...]   (no duplicate values in a, but a is very big)
b = [1, 9, 1,...]          (set(b) is a subset of set(a), 1<<len(b)<<len(a)) 

indices = get_indices_of_a(a, b)

如何让get_indices_of_a返回indices = [0, 2, 0,...],并使用array(a)[indices] = b? 是否有比使用a.index更快的方法?将b变成集合是匹配列表和返回索引的快速方法(参见compare two lists in python and return indices of matched values),但在这种情况下会失去第二个1的索引以及索引序列。
2个回答

13

a是一个大列表时,一种快速的方法是使用字典将a中的值映射到索引:

>>> index_dict = dict((value, idx) for idx,value in enumerate(a))
>>> [index_dict[x] for x in b]
[0, 2, 0]

与使用a.index所需的平方时间相比,这将在平均情况下花费线性时间。


+1。对于大型列表,这是一个很好的答案,它将显着减少所需的时间 - 自然而然,在小型列表上,创建字典所需的时间比它节省的时间更长。鉴于提问者对我的回答的评论,似乎涉及到大型列表,因此这是想要的答案。 - Gareth Latty

8

假设我们正在处理较小的列表,那么这样做非常简单:

>>> a = [1, 2, 9, 3, 8] 
>>> b = [1, 9, 1] 
>>> [a.index(item) for item in b]
[0, 2, 0]

在更大的列表上,这将变得非常昂贵。

(如果存在重复项,则结果列表中始终引用第一次出现的项,如果not set(b) <= set(a),则会出现ValueError错误)。


非常感谢!虽然b的长度远小于a,但a非常大而且b也不小。使用a.index(item)会在a中为每个b的值进行搜索...是否有更快的方法? - user1342516
@user1342516 是的,请参考interjay的回答 - Gareth Latty
你可以将以下代码添加到你的解决方案中,以避免 ValueError 的情况发生:[a.index(item) for item in b if item in a] - Ashwini Chaudhary
@AshwiniChaudhary 根据提问者的说法,我认为他宁愿出现错误也不希望默默失败。当然,如果您想跳过缺失的元素,那么可以这样做。 - Gareth Latty

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