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

2024-04-20 10:07:09 发布

您现在位置: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],而listA中的[5],但所描述的方法只会返回[4]。你知道吗


Tags: 实例方法答案示例列表链接过程数字
3条回答

创建一个包含所有索引(包括重复元素)的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),因此构建dict的成本将被任何合理大小的数据和良好的伸缩性所抵消。你知道吗

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

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]

这可能是你真正想要的:

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所说的。你知道吗

排序回答:你知道吗

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

相关问题 更多 >