Kode Python berikut tampaknya sangat bertele-tele ketika datang dari latar belakang Matlab
>>> a = [1, 2, 3, 1, 2, 3]
>>> [index for index,value in enumerate(a) if value > 2]
[2, 5]
Saat di Matlab saya bisa menulis:
>> a = [1, 2, 3, 1, 2, 3];
>> find(a>2)
ans =
3 6
Apakah ada metode tangan pendek untuk menulis ini dengan Python, atau apakah saya tetap menggunakan versi panjang?
Terima kasih atas semua saran dan penjelasan tentang alasan sintaksis Python.
Setelah menemukan yang berikut di situs web numpy, saya rasa saya telah menemukan solusi yang saya suka:
http://docs.scipy.org/doc/numpy/user/basics.indexing.html#boolean-or-mask-index-arrays
Menerapkan informasi dari situs web itu ke masalah saya di atas, akan memberikan yang berikut:
>>> from numpy import array
>>> a = array([1, 2, 3, 1, 2, 3])
>>> b = a>2
array([False, False, True, False, False, True], dtype=bool)
>>> r = array(range(len(b)))
>>> r(b)
[2, 5]
Berikut ini seharusnya berfungsi (tetapi saya belum memiliki juru bahasa Python untuk mengujinya):
class my_array(numpy.array):
def find(self, b):
r = array(range(len(b)))
return r(b)
>>> a = my_array([1, 2, 3, 1, 2, 3])
>>> a.find(a>2)
[2, 5]
[idx for idx in range(len(a)) if a[idx] > 2]
? Alasan mengapa hal ini agak canggung untuk dilakukan dengan Python adalah karena ia tidak menggunakan indeks sebanyak bahasa lain.Jawaban:
Dengan Python, Anda tidak akan menggunakan indeks untuk ini sama sekali, tetapi hanya berurusan dengan nilainya—
[value for value in a if value > 2]
. Biasanya berurusan dengan indeks berarti Anda tidak melakukan sesuatu dengan cara terbaik.Jika Anda memang membutuhkan API yang mirip dengan Matlab, Anda akan menggunakan numpy , sebuah paket untuk array multidimensi dan matematika numerik dengan Python yang sangat terinspirasi oleh Matlab. Anda akan menggunakan array numpy daripada daftar.
sumber
filtered_ranges_and_angles = [(range, angle) for range, angle in zip(ranges, angles) if should_be_kept(range)]
Cara lain:
Secara umum, ingatlah bahwa sementara
find
adalah fungsi yang sudah dimasak, pemahaman daftar adalah solusi umum, dan dengan demikian sangat kuat . Tidak ada yang menghalangi Anda untuk menulisfind
fungsi dengan Python dan menggunakannya nanti sesuai keinginan. Yaitu:Perhatikan bahwa saya menggunakan daftar di sini untuk meniru Matlab. Akan lebih Pythonic menggunakan generator dan iterator.
sumber
[i for i,v in enumerate(a) if v > 2]
gantinya.index
dengani
danvalue
denganv
dalam aslinya dan hitung karakternya.enumerate
lebih darirange(len(...))
keduanya lebih kuat dan lebih efisien.find_indices
fungsi yang akan digunakanenumerate
Bagi saya ini bekerja dengan baik:
sumber
Mungkin pertanyaan lain adalah, "apa yang akan Anda lakukan dengan indeks tersebut setelah Anda mendapatkannya?" Jika Anda akan menggunakannya untuk membuat daftar lain, maka dengan Python, itu adalah langkah tengah yang tidak perlu. Jika Anda menginginkan semua nilai yang cocok dengan kondisi tertentu, cukup gunakan filter bawaan:
Atau tulis komprhension daftar Anda sendiri:
Jika Anda ingin menghapusnya dari daftar, maka cara Pythonic tidak selalu menghapus dari daftar, tetapi menulis pemahaman daftar seolah-olah Anda sedang membuat daftar baru, dan menetapkan kembali di tempat menggunakan
listvar[:]
di sebelah kiri -sisi:Matlab memasok
find
karena model larik-sentrisnya bekerja dengan memilih item menggunakan indeks lariknya. Anda dapat melakukan ini dengan Python, tentu saja, tetapi cara yang lebih Pythonic adalah menggunakan iterator dan generator, seperti yang telah disebutkan oleh @EliBendersky.sumber
a[:] = ...
- lihat jawaban Alex Martelli untuk pertanyaan ini stackoverflow.com/questions/1352885/… .Bahkan jika itu adalah jawaban yang terlambat: Saya pikir ini masih merupakan pertanyaan yang sangat bagus dan IMHO Python (tanpa pustaka tambahan atau toolkit seperti numpy) masih kekurangan metode yang nyaman untuk mengakses indeks elemen daftar menurut filter yang ditentukan secara manual.
Anda dapat menentukan fungsi secara manual, yang menyediakan fungsionalitas itu:
Hasil: [0, 4]
Dalam imajinasi saya, cara yang sempurna adalah membuat daftar kelas anak dan menambahkan fungsi indeks sebagai metode kelas. Dengan cara ini, hanya metode filter yang dibutuhkan:
Saya menjelaskan sedikit lebih banyak tentang topik itu di sini: http://tinyurl.com/jajrr87
sumber