Apa cara tercepat untuk mengetahui apakah ada nilai dalam daftar (daftar dengan jutaan nilai di dalamnya) dan apa indeksnya?
Saya tahu bahwa semua nilai dalam daftar adalah unik seperti dalam contoh ini.
Metode pertama yang saya coba adalah (3,8 detik dalam kode asli saya):
a = [4,2,3,1,5,6]
if a.count(7) == 1:
b=a.index(7)
"Do something with variable b"
Metode kedua yang saya coba adalah (2x lebih cepat: 1,9 detik untuk kode asli saya):
a = [4,2,3,1,5,6]
try:
b=a.index(7)
except ValueError:
"Do nothing"
else:
"Do something with variable b"
Metode yang diusulkan dari pengguna Stack Overflow (2,74 detik untuk kode asli saya):
a = [4,2,3,1,5,6]
if 7 in a:
a.index(7)
Dalam kode asli saya, metode pertama membutuhkan 3,81 detik dan metode kedua membutuhkan 1,88 detik. Ini peningkatan yang bagus, tetapi:
Saya seorang pemula dengan Python / scripting, dan apakah ada cara yang lebih cepat untuk melakukan hal yang sama dan menghemat lebih banyak waktu pemrosesan?
Penjelasan lebih spesifik untuk aplikasi saya:
Di Blender API saya bisa mengakses daftar partikel:
particles = [1, 2, 3, 4, etc.]
Dari sana, saya dapat mengakses lokasi partikel:
particles[x].location = [x,y,z]
Dan untuk setiap partikel saya menguji apakah ada tetangga dengan mencari setiap lokasi partikel seperti:
if [x+1,y,z] in particles.location
"Find the identity of this neighbour particle in x:the particle's index
in the array"
particles.index([x+1,y,z])
sumber
bisect
modulJawaban:
Cara paling jelas dan tercepat untuk melakukannya.
Anda juga dapat mempertimbangkan untuk menggunakan
set
, tetapi membuat set dari daftar Anda itu mungkin memakan waktu lebih lama daripada yang akan menghemat pengujian keanggotaan. Satu-satunya cara untuk memastikan adalah melakukan benchmark dengan baik. (ini juga tergantung pada operasi apa yang Anda butuhkan)sumber
Seperti yang dinyatakan oleh orang lain,
in
bisa sangat lambat untuk daftar besar. Berikut adalah beberapa perbandingan pertunjukan untukin
,set
danbisect
. Perhatikan waktu (dalam detik) dalam skala log.Kode untuk pengujian:
sumber
import random / import bisect / import matplotlib.pyplot as plt
lalu hubungi:profile()
range()
objek yang sederhana . Saat menggunakanvar in [integer list]
, lihat apakah suaturange()
objek dapat memodelkan urutan yang sama. Sangat dekat kinerjanya dengan satu set, tetapi lebih ringkas.Anda bisa memasukkan barang Anda ke dalam
set
. Pengaturan pencarian sangat efisien.Mencoba:
sunting Di komentar, Anda mengatakan ingin mendapatkan indeks elemen. Sayangnya, set tidak memiliki gagasan tentang posisi elemen. Alternatifnya adalah dengan melakukan pre-sorting daftar Anda dan kemudian menggunakan pencarian biner setiap kali Anda perlu menemukan elemen.
sumber
Pemakaian
Saya percaya ini adalah cara tercepat untuk mengetahui apakah nilai yang dipilih ada dalam array.
sumber
return 'a' in a
?o='--skip'; o in ("--skip-ias"); # returns True !
in
operator bekerja dengan cara yang sama untuk menguji keanggotaan substring. Bagian yang membingungkan di sini mungkin("hello")
bukan tuple bernilai tunggal, sementara("hello",)
- koma yang membuat perbedaan.o in ("--skip-ias",)
adalahFalse
seperti yang diharapkan.Ini hanya akan menjadi ide yang baik jika a tidak berubah dan dengan demikian kita dapat melakukan bagian dict () sekali dan kemudian menggunakannya berulang kali. Jika a memang berubah, harap berikan detail lebih lanjut tentang apa yang Anda lakukan.
sumber
Pertanyaan aslinya adalah:
Jadi ada dua hal yang harus dicari:
Terhadap ini, saya memodifikasi kode @xslittlegrass untuk menghitung indeks dalam semua kasus, dan menambahkan metode tambahan.
Hasil
Metode adalah:
Hasil menunjukkan bahwa metode 5 adalah yang tercepat.
Menariknya, coba dan metode yang ditetapkan setara dalam waktu.
Kode Uji
sumber
Sepertinya aplikasi Anda mungkin mendapatkan keuntungan dari penggunaan struktur data Bloom Filter.
Singkatnya, pencarian filter bloom dapat memberi tahu Anda dengan sangat cepat jika nilainya TIDAK PASTI hadir dalam satu set. Jika tidak, Anda dapat melakukan pencarian lebih lambat untuk mendapatkan indeks dari nilai yang MUNGKIN MENJADI dalam daftar. Jadi jika aplikasi Anda cenderung mendapatkan hasil "tidak ditemukan" lebih sering daripada hasil "ditemukan", Anda mungkin melihat percepatan dengan menambahkan Bloom Filter.
Untuk detail, Wikipedia memberikan tinjauan yang baik tentang cara kerja Bloom Filter, dan pencarian web untuk "python bloom filter library" akan menyediakan setidaknya beberapa implementasi yang bermanfaat.
sumber
Ketahuilah bahwa
in
operator menguji tidak hanya persamaan (==
) tetapi juga identitas (is
),in
logika untuklist
s kira - kira setara dengan yang berikut (sebenarnya ditulis dalam C dan bukan Python, setidaknya dalam CPython):Dalam sebagian besar keadaan, detail ini tidak relevan, tetapi dalam beberapa keadaan mungkin membuat pemula Python terkejut, misalnya,
numpy.NAN
memiliki properti yang tidak biasa yaitu tidak sama dengan dirinya sendiri :Untuk membedakan antara kasus-kasus yang tidak biasa ini, Anda dapat menggunakan
any()
seperti:Perhatikan bahwa
in
logika untuklist
sany()
adalah:Namun, saya harus menekankan bahwa ini adalah kasus tepi, dan untuk sebagian besar kasus,
in
operator sangat dioptimalkan dan tentu saja apa yang Anda inginkan (baik dengan alist
atau dengan aset
).sumber
Atau gunakan
__contains__
:Demo:
sumber
Solusi @Winston Ewert menghasilkan percepatan besar untuk daftar yang sangat besar, tetapi jawaban stackoverflow ini menunjukkan bahwa coba: / kecuali: / lain: konstruk akan melambat jika cabang kecuali sering dicapai. Alternatifnya adalah memanfaatkan
.get()
metode untuk dikt:The
.get(key, default)
Metode ini hanya untuk kasus ketika Anda tidak dapat menjamin kunci akan di dict. Jika kunci adalah hadir, ia mengembalikan nilai (seperti yang akandict[key]
), tetapi jika tidak,.get()
mengembalikan nilai default (di siniNone
). Anda harus memastikan dalam hal ini bahwa default yang dipilih tidak akan masuka
.sumber
Ini bukan kode, tetapi algoritma untuk pencarian yang sangat cepat.
Jika daftar Anda dan nilai yang Anda cari semuanya angka, ini cukup mudah. Jika string: lihat bagian bawah:
Jika Anda juga membutuhkan posisi asli nomor Anda, cari di kolom indeks kedua.
Jika daftar Anda tidak terbuat dari angka, metode ini masih berfungsi dan akan menjadi yang tercepat, tetapi Anda mungkin perlu mendefinisikan fungsi yang dapat membandingkan / memesan string.
Tentu saja, ini membutuhkan investasi dari metode disortir (), tetapi jika Anda terus menggunakan kembali daftar yang sama untuk memeriksa, mungkin layak dilakukan.
sumber
Karena pertanyaannya tidak selalu harus dipahami sebagai cara teknis tercepat - saya selalu menyarankan cara tercepat yang paling mudah untuk memahami / menulis: pemahaman daftar, one-liner
Saya punya
list_to_search_in
dengan semua item, dan ingin mengembalikan indeks item dilist_from_which_to_search
.Ini mengembalikan indeks dalam daftar yang bagus.
Ada cara lain untuk memeriksa masalah ini - namun daftar pemahamannya cukup cepat, menambah fakta menulisnya cukup cepat, untuk menyelesaikan masalah.
sumber
Bagi saya itu adalah 0,030 detik (nyata), 0,026 detik (pengguna), dan 0,004 detik (sys).
sumber
Kode untuk memeriksa apakah ada dua elemen dalam array yang produknya sama dengan k:
sumber