如何根据给定索引获取Python列表的子列表?

55 投票
8 回答
122598 浏览
提问于 2025-04-17 22:21

我有一个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

如果你喜欢函数式编程,你可以使用maplist.__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] 是用来访问列表中某个特定位置元素的写法。

撰写回答