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

Jawaban:


241
T = [L[i] for i in Idx]

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)


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]

Ini tidak akan berhasil jika bkebetulan mengandung hanya satu item.
Blhsing


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

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


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']
Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.