Dengan Python, bagaimana cara mengindeks daftar dengan daftar lain?

130

Saya ingin mengindeks daftar dengan daftar lain seperti ini

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
T = L[ Idx ]

dan T harus menjadi daftar yang berisi ['a', 'd', 'h'].

Apakah ada cara yang lebih baik dari itu?

T = []
for i in Idx:
    T.append(L[i])

print T
# Gives result ['a', 'd', 'h']
Daniel Andrén
sumber

Jawaban:

241
T = [L[i] for i in Idx]
mobil van
sumber
7
Apakah ini lebih cepat daripada for-loop atau hanya lebih pendek?
Daniel Andrén
10
@daniel: keduanya + direkomendasikan
SilentGhost
14
Tes penghitungan waktu cepat (tanpa pysco atau apa pun, jadi buat apa pun yang Anda mau) menunjukkan daftar pemahaman 2.5x lebih cepat dari loop (1000 elemen, diulang 10.000 kali).
James Hopkin
2
(Menggunakan peta dan lambda bahkan lebih lambat - seperti yang diharapkan, karena memanggil fungsi untuk setiap iterasi)
James Hopkin
+1 Jika daftar pengindeksan adalah arbitrer, maka daftar comrpension adalah caranya. Saya pikir meskipun demikian, jika memungkinkan, yang tampaknya tidak menjadi masalah di sini, irisan bahkan lebih cepat.
Jaime
41

Jika Anda menggunakan numpy, Anda dapat melakukan irisan panjang seperti itu:

>>> import numpy
>>> a=numpy.array(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
>>> Idx = [0, 3, 7]
>>> a[Idx]
array(['a', 'd', 'h'], 
      dtype='|S1')

... dan mungkin jauh lebih cepat (jika kinerjanya cukup memprihatinkan untuk mengganggu impor yang numpy)

Paul
sumber
5
Tes timeit cepat saya menunjukkan bahwa menggunakan np.array sebenarnya hampir 3 kali lebih lambat (termasuk konversi ke array).
Andrzej Pronobis
Ini berfungsi lebih baik jika Anda perlu mengubahnya untuk operasi array. Terlalu memakan waktu untuk operasi daftar biasa.
frankliuao
9

Pendekatan fungsional:

a = [1,"A", 34, -123, "Hello", 12]
b = [0, 2, 5]

from operator import itemgetter

print(list(itemgetter(*b)(a)))
[1, 34, 12]
Padraic Cunningham
sumber
Ini tidak akan berhasil jika bkebetulan mengandung hanya satu item.
Blhsing
7
T = map(lambda i: L[i], Idx)
Mehrdad Afshari
sumber
6
perlu dikonversi ke daftar di py3k
SilentGhost
5

Saya tidak senang dengan salah satu pendekatan ini, jadi saya datang dengan Flexlistkelas yang memungkinkan pengindeksan fleksibel, baik dengan integer, slice atau daftar indeks:

class Flexlist(list):
    def __getitem__(self, keys):
        if isinstance(keys, (int, slice)): return list.__getitem__(self, keys)
        return [self[k] for k in keys]

Yang, sebagai contoh, Anda akan gunakan sebagai:

L = Flexlist(['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'])
Idx = [0, 3, 7]
T = L[ Idx ]

print(T)  # ['a', 'd', 'h']
jedwards
sumber
yang juga menunjukkan kekuatan dan fleksibilitas Python!
crowie
Sangat mudah untuk memperluas ini juga untuk kode yang ada. Cukup telepon existing_list = Flexlist(existing_list)dan kami memiliki fungsionalitas yang diperlukan tanpa melanggar kode apa pun
Yesh
1
L= {'a':'a','d':'d', 'h':'h'}
index= ['a','d','h'] 
for keys in index:
    print(L[keys])

Saya akan menggunakan yang Dict adddiinginkan keysuntukindex

pengguna4749532
sumber
0

Anda juga dapat menggunakan __getitem__metode yang digabungkan dengan mapseperti berikut ini:

L = ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h']
Idx = [0, 3, 7]
res = list(map(L.__getitem__, Idx))
print(res)
# ['a', 'd', 'h']
David S
sumber