如何根据给定索引获取Python列表的子列表?
我有一个Python的列表,比如说 a = [0,1,2,3,4,5,6]
。我还有一个索引列表,比如说 b = [0,2,4,5]
。我该怎么从列表 a
中获取索引在 b
里的元素呢?
8 个回答
4
使用列表推导式,这样应该可以工作 -
li = [a[i] for i in b]
测试这个 -
>>> a = [0,10,20,30,40,50,60]
>>> b = [0,2,4,5]
>>> li = [a[i] for i in b]
>>> li
[0, 20, 40, 50]
5
很多提出的解决方案如果 b
里有 a
中没有的索引,就会出现 KeyError
错误。如果你想跳过这些无效的索引,可以使用下面的方法。
>>> b = [0,2,4,5]
>>> a = [0,1,2,3,4,5,6]
>>> [x for i,x in enumerate(a) if i in b]
[0, 2, 4, 5]
>>> b = [0,2,4,500]
>>> [x for i,x in enumerate(a) if i in b]
[0, 2, 4]
enumerate
会生成一对对的元组,包含索引和对应的值。因为我们同时有了项目和它的索引,所以可以检查这个索引是否在 b
中。
10
如果你喜欢函数式编程,你可以使用map
和list.__getitem__
来处理数据:
>>> a = [0,1,2,3,4,5,6]
>>> b = [0,2,4,5]
>>> map(a.__getitem__, b)
[0, 2, 4, 5]
>>>
不过,在Python中,使用列表推导的方式更常见...
34
有点不同的东西...
>>> a = range(7)
>>> b = [0,2,4,5]
>>> import operator
>>> operator.itemgetter(*b)(a)
(0, 2, 4, 5)
itemgetter
这个函数可以接收一个或多个键作为参数,然后返回一个函数,这个函数会根据你给定的键,从它的参数中取出对应的项目。举个例子,上面我们创建了一个函数,它会返回索引为0、2、4和5的项目,然后把这个函数应用到a
上。
看起来它的速度比用列表推导式实现的要快很多。
In [1]: import operator
In [2]: a = range(7)
In [3]: b = [0,2,4,5]
In [4]: %timeit operator.itemgetter(*b)(a)
1000000 loops, best of 3: 388 ns per loop
In [5]: %timeit [ a[i] for i in b ]
1000000 loops, best of 3: 415 ns per loop
In [6]: f = operator.itemgetter(*b)
In [7]: %timeit f(a)
10000000 loops, best of 3: 183 ns per loop
至于为什么itemgetter
更快,原因是列表推导式需要执行额外的Python字节码。
In [3]: def f(a,b): return [a[i] for i in b]
In [4]: def g(a,b): return operator.itemgetter(*b)(a)
In [5]: dis.dis(f)
1 0 BUILD_LIST 0
3 LOAD_FAST 1 (b)
6 GET_ITER
>> 7 FOR_ITER 16 (to 26)
10 STORE_FAST 2 (i)
13 LOAD_FAST 0 (a)
16 LOAD_FAST 2 (i)
19 BINARY_SUBSCR
20 LIST_APPEND 2
23 JUMP_ABSOLUTE 7
>> 26 RETURN_VALUE
而itemgetter
只是一个用C语言实现的单一调用:
In [6]: dis.dis(g)
1 0 LOAD_GLOBAL 0 (operator)
3 LOAD_ATTR 1 (itemgetter)
6 LOAD_FAST 1 (b)
9 CALL_FUNCTION_VAR 0
12 LOAD_FAST 0 (a)
15 CALL_FUNCTION 1
18 RETURN_VALUE
70
你可以使用 列表推导式 来获取那个列表:
c = [a[index] for index in b]
print c
这和下面的写法是一样的:
c= []
for index in b:
c.append(a[index])
print c
输出结果:
[0,2,4,5]
注意:
记住,some_list[index]
是用来访问列表中某个特定位置元素的写法。