当前位置:  开发笔记 > 编程语言 > 正文

使用唯一索引索引列表

如何解决《使用唯一索引索引列表》经验,为你挑选了4个好方法。

我有一个清单说l = [10,10,20,15,10,20].我想为每个唯一值分配一个特定的"索引"来获取[1,1,2,3,1,2].

这是我的代码:

a = list(set(l))
res = [a.index(x) for x in l]

结果证明非常慢.

l拥有1M个元素和100K独特元素.我也尝试过使用lambda和排序的地图,这没有用.这样做的理想方法是什么?



1> Ashwini Chau..:

您可以O(N)使用a defaultdict和list comprehension 及时完成此操作:

>>> from itertools import count
>>> from collections import defaultdict
>>> lst = [10, 10, 20, 15, 10, 20]
>>> d = defaultdict(count(1).next)
>>> [d[k] for k in lst]
[1, 1, 2, 3, 1, 2]

在Python 3中使用__next__而不是next.


如果你想知道它是如何工作的?

传递给的default_factory(即count(1).next在这种情况下)defaultdict仅在Python遇到缺失键时被调用,因此对于10,该值将为1,然后对于接下来的10,它不再是缺失的键,因此使用先前计算的1,现在20又是一个缺失的密钥,Python将default_factory再次调用它来获取其值等等.

d 最后将看起来像这样:

>>> d
defaultdict(,
            {10: 1, 20: 2, 15: 3})



2> dsh..:

代码的缓慢产生是因为a.index(x)执行线性搜索并对其中的每个元素执行线性搜索l.因此,对于每个1M项目,您执行(最多)100K比较.

将一个值转换为另一个值的最快方法是在地图中查找.您需要创建地图并填写原始值与所需值之间的关系.然后在列表中遇到另一个相同值时从地图中检索值.

这是一个通过单个传递的示例l.可能存在进一步优化的空间,以消除res在追加时重复重新分配的需要.

res = []
conversion = {}
i = 0
for x in l:
    if x not in conversion:
        value = conversion[x] = i
        i += 1
    else:
        value = conversion[x]
    res.append(value)



3> Eugene Yarma..:

您的解决方案是缓慢的,因为它的复杂性是O(nm)m正在独特的元素个数l:a.index()O(m),你把它的每一个元素l.

为了实现它O(n),index()在字典中删除并存储索引:

>>> idx, indexes = 1, {}
>>> for x in l:
...     if x not in indexes:
...         indexes[x] = idx
...         idx += 1
... 
>>> [indexes[x] for x in l]
[1, 1, 2, 3, 1, 2]

如果l仅包含已知范围内的整数,则还可以将索引存储在列表中而不是字典中,以便更快地进行查找.



4> jfish003..:

嗯,我想这取决于你是否希望它以特定的顺序返回索引.如果您希望该示例返回:

    [1,1,2,3,1,2]

然后你可以看看提交的其他答案.但是,如果您只关心为每个唯一编号获取唯一索引,那么我可以为您提供快速解决方案

    import numpy as np
    l = [10,10,20,15,10,20]
    a = np.array(l)
    x,y = np.unique(a,return_inverse = True)

对于这个例子,y的输出是:

    y = [0,0,2,1,0,2]

我测试了1,000,000个条目,它基本上立即完成.

推荐阅读
手机用户2402851155
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有