Python многомерный список.. как захватить одно измерение?

Мой вопрос: есть ли у меня список вроде:

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] 

?

EDIT:

Эффективность вызывает большую озабоченность. Я действительно просматриваю список, содержащий более 300000 записей

Ответ 1

ИЗМЕНИТЬ: Здесь некоторые действительные цифры! Понятие 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]]))

... и в основном все, что Matlab может.

Ответ 2

Идеальный вариант для понимания :

[sublist[0] for sublist in someList]

Поскольку эффективность является серьезной проблемой, это будет намного быстрее, чем подход zip. В зависимости от того, что вы делаете с результатом, вы можете получить еще большую эффективность, используя подход выражения генератора:

(sublist[0] for sublist in someList)

Обратите внимание, что это возвращает генератор вместо списка, поэтому его нельзя индексировать.

Ответ 3

zip(*someList)[0]

EDIT:

В ответ на рекурсивный комментарий: можно также использовать

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