Ekstrak item pertama dari setiap sublist

146

Saya bertanya-tanya apa cara terbaik untuk mengekstrak item pertama dari masing-masing sublist dalam daftar daftar dan menambahkannya ke daftar baru. Jadi jika saya punya:

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

dan saya ingin menarik keluar a, 1dan xdan membuat daftar terpisah dari itu.

Saya mencoba:

lst2.append(x[0] for x in lst)
konrad
sumber
1
Kode Anda hampir benar. Satu-satunya masalah adalah penggunaan daftar pemahaman.
Abhishek Mittal

Jawaban:

198

Menggunakan pemahaman daftar :

>>> lst = [['a','b','c'], [1,2,3], ['x','y','z']]
>>> lst2 = [item[0] for item in lst]
>>> lst2
['a', 1, 'x']
alecxe
sumber
Metode pemahaman daftar juga yang tercepat, bahkan lebih cepat daripada metode Numpy. Jawaban jboi berbicara tentang perbandingan kinerja,
Qiao Zhang
83

Anda bisa menggunakan zip:

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

Atau, Python 3 di mana ziptidak menghasilkan daftar:

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

Atau,

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

Atau, (favorit saya) gunakan numpy:

>>> 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])
dawg
sumber
Belum mengunduh, tetapi cuplikan kode pertama (zip) menghasilkan: "objek 'zip' tidak dapat disubkripsikan". Python 3.6 di Jupyter.
jboi
@jboi: Hanya membungkus listdulu atau gunakan next. Terima kasih
dawg
20

Punya masalah yang sama dan penasaran dengan kinerja masing-masing solusi.

Ini dia %timeit:

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

Cara numpy pertama, mentransformasikan array:

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

Sepenuhnya asli menggunakan pemahaman daftar (seperti yang dijelaskan oleh @alecxe):

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

Cara asli lain menggunakan zip(seperti yang dijelaskan oleh @dawg):

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

Cara numpy kedua. Juga dijelaskan oleh @dawg:

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

Anehnya (yah, setidaknya bagi saya) cara asli menggunakan daftar pemahaman adalah yang tercepat dan sekitar 10x lebih cepat daripada cara numpy. Menjalankan dua cara numpy tanpa final listmenghemat sekitar satu μs yang masih dalam perbedaan 10x.

Perhatikan bahwa, ketika saya mengepung setiap cuplikan kode dengan panggilan ke len, untuk memastikan bahwa Generator berjalan hingga akhir, waktunya tetap sama.

jboi
sumber
4
ada overhead yang cukup besar saat membuat array.
hpaulj
1
setuju dengan hpaulj, jika Anda memulai dengan numpy array, [:, 0] lebih cepat. Cobalah: lst = np.array ([['a', 'b', 'c'], [1,2,3], ['x', 'y', 'z']]), lalu pertama [:, 0]. Konversi dalam contoh uji waktu memberikan pemahaman daftar keuntungan yang tidak adil. Jadi jika Anda bisa, gunakan array numpy untuk menyimpan data Anda jika kecepatan adalah tujuan utama Anda. Numpy hampir selalu lebih cepat. Itu dibangun untuk kecepatan.
spacedustpi
13

Python menyertakan fungsi yang disebut itemgetter untuk mengembalikan item pada indeks tertentu dalam daftar:

from operator import itemgetter

Lewati itemgetter () berfungsi sebagai indeks item yang ingin Anda ambil. Untuk mengambil item pertama, Anda akan menggunakan itemgetter (0). Yang penting untuk dipahami adalah itemgetter (0) itu sendiri mengembalikan fungsi. Jika Anda meneruskan daftar ke fungsi itu, Anda mendapatkan item tertentu:

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

Ini berguna ketika Anda menggabungkannya dengan map (), yang menggunakan fungsi sebagai argumen pertama, dan daftar (atau yang bisa diubah) sebagai argumen kedua. Ini mengembalikan hasil memanggil fungsi pada setiap objek di iterable:

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

Perhatikan bahwa map () mengembalikan generator, sehingga hasilnya diteruskan ke list () untuk mendapatkan daftar aktual. Singkatnya, tugas Anda dapat dilakukan seperti ini:

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

Ini adalah metode alternatif untuk menggunakan pemahaman daftar, dan metode mana yang dipilih sangat tergantung pada konteks, keterbacaan, dan preferensi.

Info lebih lanjut: https://docs.python.org/3/library/operator.html#operator.itemgetter

Christian Abbott
sumber
2

Kode Anda hampir benar. Satu-satunya masalah adalah penggunaan daftar pemahaman.

Jika Anda menggunakan like: (x [0] untuk x in lst), ia mengembalikan objek generator. Jika Anda menggunakan like: [x [0] untuk x in lst], ia mengembalikan daftar.

Saat Anda menambahkan output pemahaman daftar ke daftar, output pemahaman daftar adalah elemen tunggal dari daftar.

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']

Tolong beri tahu saya jika saya salah.

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

print(outputlist) 

Keluaran: ['a', 1, 'x']

PrabhuPrakash
sumber
0

Anda mengatakan bahwa Anda memiliki daftar yang ada. Jadi saya akan pergi dengan itu.

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

Saat ini Anda menambahkan objek generator ke daftar kedua Anda.

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

Tetapi Anda mungkin ingin itu menjadi daftar item pertama

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

Sekarang kami menambahkan daftar item pertama ke daftar yang ada. Jika Anda ingin menambahkan item tema sendiri, bukan daftar item, ke item yang ada, Anda akan menggunakan list.extend. Dalam hal ini kita tidak perlu khawatir tentang menambahkan generator, karena extended akan menggunakan generator itu untuk menambahkan setiap item yang didapatnya dari sana, untuk memperpanjang daftar saat ini.

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

atau

>>> 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#list-comprehensions

Hendrik
sumber
1
Jawaban Anda bagus dan lengkap untuk apa yang terdengar seperti yang diinginkan OP, tapi saya pikir kata appenddalam pertanyaan itu menyebabkan kebingungan. Kedengarannya seperti dia hanya ingin bagian pemahaman daftar solusi Anda.
Beroe