在Python中,如何将一个列表与另一个列表建立索引?


130

我想用这样的另一个列表索引一个列表

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
T = L[ Idx ]

T应该最终是一个包含['a','d','h']的列表。

有没有比这更好的方法

T = []
for i in Idx:
    T.append(L[i])

print T
# Gives result ['a', 'd', 'h']

Answers:


241
T = [L[i] for i in Idx]

7
这是否比for循环更快或更短?
DanielAndrén09年

10
@daniel:既有+推荐
SilentGhost

14
快速时序测试(没有pysco或任何东西,因此请按您的意愿进行)显示列表理解比循环快2.5倍(1000个元素,重复10000次)。
James Hopkin

2
(使用map和lambda甚至更慢-可以预料,因为它会为每个迭代调用一个函数)
James Hopkin,2009年

+1如果索引列表是任意的,则使用列表理解。我认为,尽管可能,但似乎在这种情况下,切片速度甚至更快。
Jaime 2009年

41

如果您使用的是numpy,则可以执行如下扩展切片:

>>> import numpy
>>> a=numpy.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
>>> Idx = [0, 3, 7]
>>> a[Idx]
array(['a', 'd', 'h'], 
      dtype='|S1')

...并且可能要快得多(如果性能足以影响numpy导入)


5
我的快速timeit测试表明,使用np.array实际上要慢将近3倍(包括到数组的转换)。
Andrzej Pronobis '16

如果您仍然需要将其转换为数组操作,它会更好。常规列表操作太耗时。
frankliuao

9

功能方法:

a = [1,"A", 34, -123, "Hello", 12]
b = [0, 2, 5]

from operator import itemgetter

print(list(itemgetter(*b)(a)))
[1, 34, 12]

如果b碰巧只包含一项,则将无法使用。
blhsing


5

我对这些方法都不满意,所以我想出了一个Flexlist类,它允许通过整数,切片或索引列表进行灵活的索引编制:

class Flexlist(list):
    def __getitem__(self, keys):
        if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
        return [self[k] for k in keys]

例如,您将其用作:

L = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Idx = [0, 3, 7]
T = L[ Idx ]

print(T)  # ['a', 'd', 'h']

这也展示了Python的强大功能和灵活性!
crowie

对现有代码进行扩展也很容易。只需拨打existing_list = Flexlist(existing_list)我们有所需的功能没有打破任何代码
Yesh

1
L= {'a':'a','d':'d', 'h':'h'}
index= ['a','d','h'] 
for keys in index:
    print(L[keys])

我会用一个Dict add想要keysindex


0

您也可以将__getitem__方法与map以下方法结合使用:

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.