你可以创建一个字典或defaultdict(list),将每个元素映射到它出现的索引(或索引)。这样,你需要一些更多的空间(比原始列表略多,但仍在同一范围内),但一旦创建了字典,每个索引查找将是O(1)。
>>> lst = [random.randint(0, 100) for _ in range(100)]
>>> indices = collections.defaultdict(list)
>>> for i, e in enumerate(lst):
... indices[e].append(i)
...
>>> indices[30]
[21, 28, 89]
针对您的具体问题,您可以尝试类似于以下的方法:
>>> aa = [random.randint(0, 10) for _ in range(20)] # [3, 9, 4, 5, 6, 5, 2, 4, 7, 4, 4, 9, 10, 8, 8, 7, 6, 3, 3, 3]
>>> bb = [random.randint(0, 10) for _ in range(20)] # [10, 7, 4, 9, 8, 4, 10, 7, 9, 1, 4, 8, 8, 3, 8, 0, 1, 10, 1, 6]
>>> aa_indices = {e: i for (i, e) in reversed(list(enumerate(aa)))} # {2: 6, 3: 0, 4: 2, 5: 3, 6: 4, 7: 8, 8: 13, 9: 1, 10: 12}
>>> b_in_a = [aa_indices.get(b, -1) for b in bb]
>>> b_in_a
[12, 8, 2, 1, 13, 2, 12, 8, 1, -1, 2, 13, 13, 0, 13, -1, -1, 12, -1, 4]
注意:这里使用
reversed
,因为否则字典会包含给定元素的
最后一个 索引。
使用 IPython 的
%timeit
进行一些时间分析:这种方法仅需要 2.24 毫秒来创建字典和另外 2.88 毫秒来创建最终列表,而原始方法需要 173 毫秒。
>>> %timeit [index_withoutexception(bb,i) for i in aa]
10 loops, best of 3: 173 ms per loop
>>> %timeit bb_indices = {e: i for (i, e) in reversed(list(enumerate(bb)))}
100 loops, best of 3: 2.24 ms per loop
>>> %timeit [bb_indices.get(i, -1) for i in aa]
100 loops, best of 3: 2.88 ms per loop
O(1)
,而不是O(n)
。 - Tadhg McDonald-Jensenindex()
只会返回第一次出现的位置。你想如何处理? - user6025378