我的问题是,我有一个如下列表:
someList = [[0,1,2],[3,4,5],[6,7,8]]
我如何获得每个子列表的第一个条目?
我知道我可以这样做:
newList = []
for entry in someList:
newList.append(entry[0])
其中newList将是:
[0, 3, 6]
但有没有办法做一些事情:
newList = someList[:][0]
编辑:
效率非常令人担忧。我实际上正在浏览一个包含超过300000个条目的列表
答案 0 :(得分:17)
izip
,列表理解和numpy
这样做的方式速度大致相同。
# zip
>>> timeit.timeit( "newlist = zip(*someList)[0]", setup = "someList = [range(1000000), range(1000000), range(1000000)]", number = 10 )
1.4984046398561759
# izip
>>> timeit.timeit( "newlist = izip(*someList).next()", setup = "someList = range(1000000), range(1000000), range(1000000)]; from itertools import izip", number = 10 )
2.2186223645803693e-05
# list comprehension
>>> timeit.timeit( "newlist = [li[0] for li in someList]", setup = "someList = [range(1000000), range(1000000), range(1000000)]", number = 10 )
1.4677040212518477e-05
# numpy
>>> timeit.timeit( "newlist = someList[0,:]", setup = "import numpy as np; someList = np.array([range(1000000), range(1000000), range(1000000)])", number = 10 )
6.6217344397045963e-05
>>>
对于像这样的大型数据结构,你应该使用numpy
,它在C中实现一个数组类型,因此效率更高。它还提供了您想要的所有矩阵操作。
>>> import numpy as np
>>> foo = np.array([[0,1,2],[3,4,5],[6,7,8]])
>>> foo[:,0]
array([0, 3, 6])
你也可以转置......
>>> foo.transpose()
array([[0, 3, 6],
[1, 4, 7],
[2, 5, 8]])
...使用n维数组...
>>> foo = np.zeros((3,3,3))
>>> foo
array([[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]],
[[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]]])
>>> foo[0,...]
array([[ 0., 0., 0.],
[ 0., 0., 0.],
[ 0., 0., 0.]])
..做高效的线性代数......
>>> foo = no.ones((3,3))
>>> np.linalg.qr(foo)
(array([[-0.57735027, 0.81649658, 0. ],
[-0.57735027, -0.40824829, -0.70710678],
[-0.57735027, -0.40824829, 0.70710678]]), array([[ -1.73205081e+00, -1.
73205081e+00, -1.73205081e+00],
[ 0.00000000e+00, -1.57009246e-16, -1.57009246e-16],
[ 0.00000000e+00, 0.00000000e+00, 0.00000000e+00]]))
...基本上做anything that Matlab can。
答案 1 :(得分:10)
list comprehension的完美案例:
[sublist[0] for sublist in someList]
由于效率是一个主要问题,这将比zip
方法快得多。根据您对结果所做的工作,您可以通过使用生成器表达式方法获得更高的效率:
(sublist[0] for sublist in someList)
请注意,这会返回生成器而不是列表,因此无法将其编入索引。
答案 2 :(得分:8)
zip(*someList)[0]
编辑:
回应递归的评论:人们也可以使用
from itertools import izip
izip(*someList).next()
以获得更好的表现。
一些时间分析:
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; newlist = zip(*someList)[0]"
10 loops, best of 3: 498 msec per loop
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; from itertools import izip; newlist = izip(*someList).next()"
10 loops, best of 3: 111 msec per loop
python -m timeit "someList = [range(1000000), range(1000000), range(1000000)]; newlist = [li[0] for li in someList]"
10 loops, best of 3: 110 msec per loop
所以izip和列表理解在同一个联盟中发挥作用。
当你需要一个非0的索引时,列表理解会更灵活,而且更明确。
EDIT2:
即使是numpy解决方案也不是那么快(但我可能选择了一个非代表性的例子):
python -m timeit "import numpy as np; someList = np.array([range(1000000), range(1000000), range(1000000)]); newList = someList[:,0]"
10 loops, best of 3: 551 msec per loop