列表交集指数

时间:2018-01-10 02:36:38

标签: python list

给出两个相等长度的列表:

_list = [1, 4, 8, 7, 3, 15, 5, 0, 6]
_list2 = [7, 4, 0, 1, 5, 5, 7, 2, 2]

如何尝试获取这样的输出:

output = [(0,3), (1,1), (3,0), (6,4), (6,5), (7,2)]

这里获得了两个列表的交集和共同元素'索引排列在列表中:

output = list of (index of an element in _list, where it appears in _list2)

尝试与集合交集不是一个选项,因为集合删除了重复元素。

3 个答案:

答案 0 :(得分:2)

Basic-Intermediate :作为生成器:

def find_matching_indices(a, b):
    for i, x in enumerate(a):
        for j, y in enumerate(b):
            if x == y:
                yield i, j

list(find_matching_indices(list1_, list2_))
# [(0, 3), (1, 1), (3, 0), (3, 6), (6, 4), (6, 5), (7, 2)] 

Basic-Intermediate :作为列表理解:

[(i, j)  for i, x in enumerate(list1_) for j, y in enumerate(list2_) if x == y]
# [(0, 3), (1, 1), (3, 0), (3, 6), (6, 4), (6, 5), (7, 2)] 

这些解决方案涉及两个循环。

中级 - 高级:为了好玩,词典是您可能考虑的另一种数据结构:

import collections as ct

import more_itertools as mit


def locate_indices(a, b):
    """Return a dictionary of `a` index keys found at `b` indices."""
    dd = ct.defaultdict(list)
    for i, y in enumerate(a):
        idxs = list(mit.locate(b, lambda z: z == y))
        if idxs: dd[i].extend(idxs)
    return dd


locate_indices(list1_, list2_)
# defaultdict(list, {0: [3], 1: [1], 3: [0, 6], 6: [4, 5], 7: [2]})

请注意列表a的索引是字典中的键。列出b列表中共享相同值的所有索引都将被追加。

使用了defaultdict,因为它有助于使用列表值构建字典。查看third-party tool more_itertools.locate()上的更多信息,它只会产生满足lambda条件的所有索引 - 列表a中的项目也可以在b中找到。

答案 1 :(得分:2)

from itertools import product
from collections import defaultdict


def mathcing_indices(*lists):
    d = defaultdict(lambda: tuple([] for _ in range(len(lists))))
    for l_idx, l in enumerate(lists):
        for i, elem in enumerate(l):
            d[elem][l_idx].append(i)
  return sorted([tup for _, v in d.items() for tup in product(*v)])

此解决方案构建一个字典,用于跟踪值在输入列表中显示的索引。因此,如果值5出现在第一个列表的索引0和2以及第二个列表的索引3中,则字典中5的值将为([0, 2], [3])

然后使用itertools.product构建这些索引的所有组合。

这看起来比这里的其他答案更复杂,但因为它是O(nlogn)而不是O(n**2),它是significantly faster,特别是对于大输入。两个长度为1000的随机数列表0-1000使用上述算法在~4秒内完成100次测试,在此使用其他一些时间完成6-13秒

答案 2 :(得分:0)

这是在O(n log n)中运行的解决方案:

ind1 = numpy.argsort(_list)
ind2 = numpy.argsort(_list2)
pairs = []
i = 0
j = 0
while i<ind1.size and j<ind2.size:
    e1 = _list[ind1[i]]
    e2 = _list2[ind2[j]]
    if e1==e2:
        pairs.append((ind1[i],ind2[j]))
        i = i + 1
        j = j + 1
    elif e1<e2:
        i = i +1
    elif e2<e1:
        j = j + 1
print(pairs)