python多维列表。。如何抓住一维?

2024-06-26 03:30:33 发布

您现在位置: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] 

是吗?

编辑:

效率是人们非常关心的问题。我正在浏览一个超过300000条的列表


Tags: 方法in编辑列表for条目效率entry
4条回答

一个list comprehension的完美案例:

[sublist[0] for sublist in someList]

由于效率是一个主要问题,这将比zip方法快得多。根据您对结果所做的操作,您可以使用生成器表达式方法获得更高的效率:

(sublist[0] for sublist in someList)

请注意,这将返回一个生成器而不是一个列表,因此无法索引到。

编辑:这是一些实际数字!做这件事的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
>>>

对于像这样的大型数据结构,您应该使用^{},它在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

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

所以伊兹普和列表理解在同一个联盟里玩。

当然,当需要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

一个list comprehension的完美案例:

[sublist[0] for sublist in someList]

由于效率是一个主要问题,这将比zip方法快得多。根据您对结果所做的操作,使用生成器表达式方法可以获得更高的效率:

(sublist[0] for sublist in someList)

请注意,这将返回一个生成器而不是一个列表,因此无法索引到。

相关问题 更多 >