如何查找列表A中也在列表B中的项目索引

时间:2015-04-24 19:10:08

标签: python

我有listA,其中包含

[0, 20, 40, 60, 80, 80, 100, 120, 140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340]

listB,其中包含

[87, 78343, 100, 38, 100, 20, 80]

我希望能够找到listA中同样位于listB的数字索引。

例如,listAlistB共享100,100,20和80. listA中这些整数的索引是

[6, 6, 1, 4, 5]

是否有一个过程会为我找到这个,所以我不必亲手操作?

这类似于this question。区别在于我必须知道索引,即使它在任一列表中多次出现,而该链接的答案仅适用于实例的第一个示例:即listB中的80位于[4]并且[5]在listA上,但所描述的方法只会返回[4]。

4 个答案:

答案 0 :(得分:2)

创建一个dict来保存包含重复元素的所有索引,然后使用list comp为常用元素添加索引:

from collections import defaultdict

d = defaultdict(list)

for i, ele in enumerate(A):
    d[ele].append(i)

print([ele for i in B  for ele in d[i] if i in d])
[6, 6, 1, 4, 5]

如果我们再添加几个80,你可以看到它返回所有适当的索引:

A = [0, 20, 40, 60, 80, 80, 100, 80, 120, 80,140, 160, 180, 200, 220, 240, 260, 280, 300, 320, 340,21]


B = [87, 78343, 100, 38, 100, 20, 80]

from collections import defaultdict

d = defaultdict(list)

for i, ele in enumerate(A):
    d[ele].append(i)

print([ele for i in B for ele in d[i] if i in d])
[6, 6, 1, 4, 5, 7, 9, 21]

对于大型列表,这将非常有效,查找和0(1)因此构建字典的成本将抵消任何合理大小的数据并且可以很好地扩展。

有一点不清楚,如果两个列表中都有重复的条目会发生什么,例如:

A = [1, 2, 2, 3, 3, 4, 5] 
B = [3, 4, 3, 5]

变为:

[3, 4, 5 3, 4, 6]

其中3,4出现两次,因为两者都重复了3次。

如果是这种情况,你也可以在b中保留元素的数量:

from collections import defaultdict, Counter

d = defaultdict(list)
for i, ele in enumerate(A):
    d[ele].append(i)

cn = Counter(B)
l = []
for i in B:
    if i in d:
        val = d[i]
        l.extend(val.pop(0) if len(val) > 1 and cn[i] > 1 else ele for ele in val)
print(l)
[3, 5, 4, 6]

但是如果项目出现在B中3次,那么您将在A中获得最后一次出现的索引的第一个值:

 A = [1, 2, 2, 3, 3, 4, 5]
 B = [3, 4, 3, 5, 3]
 [3, 5, 4, 6, 4]

答案 1 :(得分:1)

这可能是你真正想要的:

wanted_indexes = [index for index, value in enumerate(listA) if value in listB]

对于您的示例listAlistB,这将生成

[1, 4, 5, 6]

这为您提供listA中同样位于listB的所有项目的索引。如果你真的想要重复,那么你可以使用它:

dups_included = [index for b_value in listB for index, a_value in enumerate(listA) if a_value == b_value]

这将生成您提供的列表作为示例:

[6, 6, 1, 4, 5]

提升效果

如果您担心运行时间,可以对每种方法进行一些优化。对于第一个,创建一个基于listB的集合并使用 -

setB = set(listB)
wanted_indexes = [index for index, value in enumerate(listA) if value in setB]

集合中的查找比列表中的查找要快得多,所以除非setB非常小,否则这会给你带来性能提升。

对于具有重复项的版本,您需要创建一个字典,将listA中的每个值映射到它出现的索引列表。然后,当您在listB中进行迭代时,您可以使用此查找表而不是通过listA进行迭代来获取索引。这正是Padraic did in his answer

答案 2 :(得分:0)

排序答案: -

>>>reduce(lambda x, y: x+y, [[index for index,value in  enumerate(listA) if item == value] for item in listB if item in listA])
[6, 6, 1, 4, 5]

长答案: -

>>>def get_common_items_index(listA,listB):
       result = []
       common_items = [item for item in listB if item in listA]
       for each_item in common_items:
           for index,value in enumerate(listA):
               if value == each_item:
                   result.append(index)
       return result

>>> get_common_items_index(listA,listB)
[6, 6, 1, 4, 5]

答案 3 :(得分:-1)

几乎与vguzmanp answer

相似
r=[]
for i in range(len(listA)):
    for _ in range(listB.count(listA[i])):
        r.append(i)