Python 多维列表.. 怎样获取一个维度?

13 投票
3 回答
17496 浏览
提问于 2025-04-16 03:54

我有一个这样的列表:

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 能做的事情

撰写回答