Python 多维列表.. 怎样获取一个维度?
我有一个这样的列表:
someList = [[0,1,2],[3,4,5],[6,7,8]]
我想知道怎么才能获取每个子列表的第一个元素?
我知道我可以这样做:
newList = []
for entry in someList:
newList.append(entry[0])
这样得到的新列表会是:
[0, 3, 6]
但是有没有办法可以像这样做:
newList = someList[:][0]
?
补充说明:
效率非常重要。我实际上是在处理一个有超过30万个条目的列表。
3 个回答
8
zip(*someList)[0]
编辑:
针对recursive的评论:你也可以使用
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时,列表推导式更灵活,也更明确。
编辑2:
即使是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
10
这是一个使用列表推导式的完美例子:
[sublist[0] for sublist in someList]
因为效率是一个很重要的问题,这种方法比使用zip
的方式要快得多。根据你对结果的处理方式,你甚至可以通过使用生成器表达式的方法来获得更高的效率:
(sublist[0] for sublist in someList)
不过要注意,这种方法返回的是一个生成器,而不是一个列表,所以不能像列表那样通过索引来访问。
16
编辑:这里有一些实际的数据!使用 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]])
...处理多维数组...
>>> 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]]))
...基本上可以做 任何 Matlab 能做的事情。