查找长列表中多个元素的索引

时间:2018-01-18 20:36:05

标签: python

我有一个非常长的lst包含唯一元素。我想设计一个函数,它将元素列表作为输入,它可以有效地返回索引列表。我们假设找到索引所需的项目都在lst

以下是一个例子:

lst = ['ab','sd','ef','de']
items_to_find = ['sd', 'ef', 'sd']
>>> fo(lst, items_to_find)  
# Output: [1,2,1]

我有一个属于自己的解决方案,但看起来效率不高。

>> [lst.index(x) for x in items_to_find]

因为lst很长,我需要一个非常快速的算法来解决它。

5 个答案:

答案 0 :(得分:6)

首先创建一个包含列表中每个项目的索引位置的字典(您声明所有项目都是唯一的,因此重复键没有问题。)

然后使用字典查找每个项目的索引位置,即平均时间复杂度O(1)。

&sslverifycertificate=false

答案 1 :(得分:2)

您可以使用包含来自lst的元素的字典作为键和索引以及值。在字典中搜索是O(1)。

答案 2 :(得分:0)

虽然您接受的答案非常好,但这里的内存效率更高,而且可能几乎一样快。但是@ Alexander的answer如果列表很长(因为其中的元素都是唯一的),就会创建一个可能很大的字典。

下面的代码还构建了一个字典来加速搜索,但它是针对目标元素的,因此可能比搜索列表小得多。对于示例数据,它创建的数据(名为targets)仅包含:{'sd': [0, 2], 'ef': [1]}

它通过序列并检查其中的每个值是目标,如果是,则根据更新结果列表。这种方法需要更多的代码才能实现,因为设置稍微复杂一些,所以这是另一种权衡。

def find_indices(seq, elements):
    targets = {}
    for index, element in enumerate(elements):
        targets.setdefault(element, []).append(index)
    indices = [None for _ in elements]  # Pre-allocate.

    for location, value in enumerate(seq):
        if value in targets:
            for element, indexes in targets.items():
                if element == value:
                    for index in indexes:
                        indices[index] = location
    return indices

lst = ['ab', 'sd', 'ef', 'de']

indices = find_indices(lst, ['sd', 'ef', 'sd'])
print(indices)  # -> [1, 2, 1]

答案 3 :(得分:0)

简单的第一近似......

def get_indices(data_list, query_list):
    datum_index_mapping = {datum:None for datum in query_list}
    for index, datum in enumerate(data_list):
        if datum in datum_index_mapping:
            datum_index_mapping[datum] = index
    return [datum_index_mapping[d] for d in query_list]

以上是最简单,最直观的解决方案,它可以提高效率(只需要为实际想要查找的元素存储索引字典)。

然而,它受到这样的事实 - 即使初始查询列表非常短 - 它将遍历整个数据列表/数据生成器。此外,它必须在每次看到之前看到的值时写入字典。下面修复了那些效率低下的问题,虽然它增加了集合的开销,因此它必须为查询列表中的每个唯一元素执行集合写入,以及为查询列表中的每个唯一元素写入字典。

def get_indices(data_list, query_list):
    not_found = set(query_list)
    datum_index_mapping = {}
    for index, datum in enumerate(data_list):
        if datum in not_found:
            datum_index_mapping[datum] = index
            not_found.remove(datum)
            if len(not_found) == 0:
                break
    return [datum_index_mapping[d] for d in query_list]

显然,根据您的程序,您可能根本不想拥有索引列表,只需让您的函数返回映射。 如果您要解析多个任意查询列表,您可能只想在其他答案显示的原始数据集上执行enumerate(),并保留将值映射到内存中的索引以及查询目的的字典。 / p>

有效率往往取决于更大的计划;我们所能做的就是进行优化。它还取决于内存层次结构和处理能力(即我们可以并行化吗?计算更昂贵,还是内存更昂贵?如果我们需要回退交换,I / O会是什么?)。

答案 4 :(得分:0)

如果您确定所有搜索到的值实际上都存在于搜索列表中并且对lst进行了排序(当然,排序本身可能需要一些时间),则可以一次性完成(线性复杂度):

def sortedindex(lst,find):
    find.sort()
    indices  = []
    start = 0
    for item in find:
        start = lst.index(item,start)
        indices.append(start)
    return indices

“开始”显示第一个索引,算法从该索引开始将检查的项目与主列表中的项目进行比较。找到正确的索引后,它将成为下一个起始标记。因为两个列表都以相同的方式排序,所以您不必担心会跳过下一个项目。