Her alt listenin ilk öğesini çıkart


148

Bir liste listesindeki her alt listenin ilk öğesini ayıklamanın ve yeni bir listeye eklemenin en iyi yolunun ne olduğunu merak ediyorum. Eğer varsa:

lst = [[a,b,c], [1,2,3], [x,y,z]]

ve ben dışarı çıkarmak istiyor a, 1ve xve bu ayrı bir liste oluşturun.

Denedim:

lst2.append(x[0] for x in lst)

1
Kodunuz neredeyse doğrudur. Tek mesele liste kavrayışının kullanılmasıdır.
Abhishek Mittal

Yanıtlar:


199

Liste kavrayışı kullanma :

>>> lst = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [item[0] for item in lst]
>>> lst2
['a', 1, 'x']

Liste anlama yöntemi de Numpy yönteminden daha hızlı, hatta daha hızlıdır. jboi'nin cevabı performans karşılaştırması hakkında konuşuyor,
Qiao Zhang

83

Zip kullanabilirsiniz:

>>> lst=[[1,2,3],[11,12,13],[21,22,23]]
>>> zip(*lst)[0]
(1, 11, 21)

Veya zipbir liste üretmeyen Python 3 :

>>> list(zip(*lst))[0]
(1, 11, 21)

Veya,

>>> next(zip(*lst))
(1, 11, 21)

Veya, (benim favorim) numpy kullanın:

>>> import numpy as np
>>> a=np.array([[1,2,3],[11,12,13],[21,22,23]])
>>> a
array([[ 1,  2,  3],
       [11, 12, 13],
       [21, 22, 23]])
>>> a[:,0]
array([ 1, 11, 21])

İndirilmemis ancak ilk kod snippet'i (zip) üretir: "'zip' nesnesi abone olamaz". Jupyter üzerinde Python 3.6.
jboi

@jboi: listÖnce etrafına sarın veya kullanın next. Teşekkürler
dawg

20

Aynı sorun vardı ve her çözümün performansını merak ettim.

İşte %timeit:

import numpy as np
lst = [['a','b','c'], [1,2,3], ['x','y','z']]

Diziyi dönüştüren ilk numpy-yolu:

%timeit list(np.array(lst).T[0])
4.9 µs ± 163 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Liste kavrama özelliğini kullanarak tamamen yerel (@alecxe tarafından açıklandığı gibi):

%timeit [item[0] for item in lst]
379 ns ± 23.1 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Başka bir yerel yöntem zip(@dawg tarafından açıklandığı gibi):

%timeit list(zip(*lst))[0]
585 ns ± 7.26 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

İkinci numpy-yolu. Ayrıca @dawg:

%timeit list(np.array(lst)[:,0])
4.95 µs ± 179 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

Şaşırtıcı bir şekilde (iyi, en azından benim için) liste kavrayışı kullanan yerel yol, en hızlı ve yaklaşık 10 kat daha hızlıdır. Final olmadan iki numpy yolunu çalıştırmaklist , hala 10x farkında olan yaklaşık bir µs tasarrufu sağlar.

Her kod snippet'ini bir çağrı ile kuşattığımda len, Jeneratörlerin sonuna kadar çalışmasını sağlamak için zamanlamanın aynı kaldığını unutmayın.


4
bir dizi oluştururken önemli bir ek yük var.
hpaulj

1
hpaulj ile anlaşın, eğer numpy dizisi ile başlarsanız, [:, 0] daha hızlıdır. Bir deneyin: lst = np.array ([['a', 'b', 'c'], [1,2,3], ['x', 'y', 'z']]), sonra [:, 0]. Örnek zaman denemelerindeki dönüşüm, liste kavrayışına haksız bir avantaj sağlar. Eğer yapabiliyorsanız, hız nihai hedefinizse verilerinizi saklamak için numpy dizisi kullanın. Numpy neredeyse her zaman daha hızlıdır. Hız için üretildi.
spacedustpi

13

Python, öğeyi listedeki belirli bir dizine döndürmek için itemgetter adlı bir işlev içerir:

from operator import itemgetter

Geri almak istediğiniz öğenin dizinini itemgetter () işlevine iletin. İlk öğeyi almak için itemgetter (0) kullanırsınız. Anlaşılması gereken önemli şey, itemgetter (0) 'ın kendisinin bir işlev döndürmesidir. Bu işleve bir liste iletirseniz, belirli bir öğeyi alırsınız:

itemgetter(0)([10, 20, 30]) # Returns 10

Bu işlevi bir işlevi ilk argüman olarak alan map () ve ikinci argüman olarak bir liste (ya da başka bir yinelenebilir) ile birleştirdiğinizde yararlıdır. Yinelenebilir her nesnede işlevi çağırmanın sonucunu döndürür:

my_list = [['a', 'b', 'c'], [1, 2, 3], ['x', 'y', 'z']]
list(map(itemgetter(0), my_list)) # Returns ['a', 1, 'x']

Map () öğesinin bir jeneratör döndürdüğünü unutmayın, böylece sonuç gerçek bir liste almak için list () öğesine iletilir. Özetle, göreviniz şu şekilde yapılabilir:

lst2.append(list(map(itemgetter(0), lst)))

Bu, bir liste kavrayışı kullanmak için alternatif bir yöntemdir ve hangi yöntemi seçmek büyük ölçüde bağlama, okunabilirliğe ve tercihe bağlıdır.

Daha fazla bilgi: https://docs.python.org/3/library/operator.html#operator.itemgetter


2

Kodunuz neredeyse doğrudur. Tek mesele liste kavrayışının kullanılmasıdır.

Like: (x içinde lst için x [0]) kullanırsanız, bir jeneratör nesnesi döndürür. Like: [x [0] lst'deki x için] kullanırsanız, bir liste döndürür.

Liste anlama çıktısını bir listeye eklediğinizde, liste anlama çıktısı listenin tek öğesidir.

lst = [["a","b","c"], [1,2,3], ["x","y","z"]]
lst2 = []
lst2.append([x[0] for x in lst])
print lst2[0]

lst2 = [['a', 1, 'x']]

lst2 [0] = ['a', 1, 'x']

Lütfen yanlış olduğumu bana bildirin.


1
lst = [['a','b','c'], [1,2,3], ['x','y','z']]
outputlist = []
for values in lst:
    outputlist.append(values[0])

print(outputlist) 

Çıktı: ['a', 1, 'x']


0

Mevcut bir listeniz olduğunu söylediniz. Ben de bununla gideceğim.

>>> lst1 = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [1, 2, 3]

Şu anda jeneratör nesnesini ikinci listenize ekliyorsunuz.

>>> lst2.append(item[0] for item in lst)
>>> lst2
[1, 2, 3, <generator object <genexpr> at 0xb74b3554>]

Ama muhtemelen ilk öğelerin listesi olmasını istiyorsunuz

>>> lst2.append([item[0] for item in lst])
>>> lst2
[1, 2, 3, ['a', 1, 'x']]

Şimdi ilk listeyi mevcut listeye ekledik. Var olan öğelere bir liste değil kendileri eklemek isterseniz list.extend komutunu kullanırsınız. Bu durumda, bir jeneratör ekleme konusunda endişelenmemize gerek yoktur, çünkü ext, geçerli listeyi genişletmek için oradan aldığı her öğeyi eklemek için bu jeneratörü kullanacaktır.

>>> lst2.extend(item[0] for item in lst)
>>> lst2
[1, 2, 3, 'a', 1, 'x']

veya

>>> lst2 + [x[0] for x in lst]
[1, 2, 3, 'a', 1, 'x']
>>> lst2
[1, 2, 3]

https://docs.python.org/3.4/tutorial/datastructures.html#more-on-lists https://docs.python.org/3.4/tutorial/datastructures.html#more-on-lists https://docs.python.org/3.4/tutorial/datastructures.html#list-comprehensions


1
Cevabınız, OP'nin istediği gibi göründüğü için güzel ve eksiksiz , ancak appendsorudaki kelimenin karışıklığa neden olduğunu düşünüyorum . Çözümünüzün liste anlama bölümünü istediği anlaşılıyor.
beroe
Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.