使用给定的索引获取 Python 列表的子列表?
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/22412509/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Getting a sublist of a Python list, with the given indices?
提问by becko
I have a Python list, say a = [0,1,2,3,4,5,6]. I also have a list of indices, say b = [0,2,4,5]. How can I get the list of elements of awith indices in b?
我有一个 Python 列表,比如a = [0,1,2,3,4,5,6]. 我还有一个索引列表,比如b = [0,2,4,5]. 我怎样才能得到a带索引的元素列表b?
采纳答案by Christian
You can use list comprehensionto get that list:
您可以使用列表理解来获取该列表:
c = [a[index] for index in b]
print c
This is equivalent to:
这相当于:
c= []
for index in b:
c.append(a[index])
print c
Output:
输出:
[0,2,4,5]
Note:
笔记:
Remember that some_list[index]is the notation used to access to an element of a listin a specific index.
请记住,这some_list[index]是用于访问list特定索引中 a元素的表示法。
回答by Kamehameha
Using List Comprehension,this should work -
使用列表理解,这应该有效 -
li = [a[i] for i in b]
Testing this -
测试这个 -
>>> 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]
回答by chepner
Something different...
有些不同...
>>> a = range(7)
>>> b = [0,2,4,5]
>>> import operator
>>> operator.itemgetter(*b)(a)
(0, 2, 4, 5)
The itemgetterfunction takes one or more keys as arguments, and returns a function which will return the items at the given keys in itsargument. So in the above, we create a function which will return the items at index 0, index 2, index 4, and index 5, then apply that function to a.
该itemgetter函数将一个或多个键作为参数,并返回一个函数,该函数将返回其参数中给定键处的项目。因此,在上面,我们创建了一个函数,该函数将返回索引 0、索引 2、索引 4 和索引 5 处的项目,然后将该函数应用于a。
It appears to be quite a bit faster than the equivalent list comprehension
它似乎比等效的列表理解要快得多
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
As for why itemgetteris faster, the comprehension has to execute extra Python byte codes.
至于为什么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
While itemgetteris a single call implemented in C:
虽然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
回答by Brian
Many of the proposed solutions will produce a KeyErrorif bcontains an index not present in a. The following will skip invalid indices if that is desired.
许多提议的解决方案将产生一个KeyErrorifb包含一个不存在的索引a。如果需要,以下将跳过无效索引。
>>> 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]
enumerateproduces tuples of index,value pairs. Since we have both the item and its index, we can check for the presence of the index in b
enumerate产生索引,值对的元组。由于我们同时拥有项目及其索引,我们可以检查 b 中是否存在索引
回答by Brian
If you are a fan of functional programming, you could use mapand list.__getitem__:
如果你是函数式编程的粉丝,你可以使用mapand list.__getitem__:
>>> a = [0,1,2,3,4,5,6]
>>> b = [0,2,4,5]
>>> map(a.__getitem__, b)
[0, 2, 4, 5]
>>>
The list comprehension approach is more canonical in Python though...
列表理解方法在 Python 中更为规范......
回答by Alex Thornton
Yet another alternative for better performance if that is important to you- it is by no means the most Pythonic but I am pretty sure it is the most efficient:
如果这对您很重要,则还有另一种更好的性能替代方案 - 它绝不是最 Pythonic 但我很确定它是最有效的:
>>> list(filter(lambda x: a.index(x) in b, a))
[0, 2, 4, 5]
Note:You do not need to convert to a listin Python 2. However you do in Python 3 onwards (if any future visitors may have a similar issue).
注意:您不需要list在 Python 2 中转换为 a 。但是您在 Python 3 中可以这样做(如果未来的访问者可能遇到类似问题)。
回答by Sklavit
A bit of speed comparison for all mentioned methods and others from Python dictionary: Get list of values for list of keys:
对所有提到的方法和Python 字典中的其他方法进行一些速度比较:获取键列表的值列表:
Python 2.7.11 |Anaconda 2.4.1 (64-bit)| (default, Jan 19 2016, 12:08:31) [MSC v.1500 64 bit (AMD64)] on win32
In[2]: import numpy.random as nprnd
idx = nprnd.randint(1000, size=10000)
l = nprnd.rand(1000).tolist()
from operator import itemgetter
import operator
f = operator.itemgetter(*idx)
%timeit f(l)
%timeit list(itemgetter(*idx)(l))
%timeit [l[_] for _ in idx] # list comprehension
%timeit map(l.__getitem__, idx)
%timeit list(l[_] for _ in idx) # a generator expression passed to a list constructor.
%timeit map(lambda _: l[_], idx) # using 'map'
%timeit [x for i, x in enumerate(l) if i in idx]
%timeit filter(lambda x: l.index(x) in idx, l) # UPDATE @Kundor: work only for list with unique elements
10000 loops, best of 3: 175 μs per loop
1000 loops, best of 3: 707 μs per loop
1000 loops, best of 3: 978 μs per loop
1000 loops, best of 3: 1.03 ms per loop
1000 loops, best of 3: 1.18 ms per loop
1000 loops, best of 3: 1.86 ms per loop
100 loops, best of 3: 12.3 ms per loop
10 loops, best of 3: 21.2 ms per loop
So the fastest is f = operator.itemgetter(*idx); f(l)
所以最快的是 f = operator.itemgetter(*idx); f(l)
回答by Temak
Using numpy.asarray. Numpy allows getting subarray of array by list of indices.
使用numpy.asarray. Numpy 允许通过索引列表获取数组的子数组。
>>> import numpy as np
>>> a = [0,10,20,30,40,50,60]
>>> b = [0,2,4,5]
>>> res = np.asarray(a)[b].tolist()
>>> res
[0, 20, 40, 50]

