Saya memiliki daftar yang terdiri dari 20.000 daftar. Saya menggunakan elemen ke-3 daftar masing-masing sebagai bendera. Saya ingin melakukan beberapa operasi pada daftar ini selama setidaknya satu flag elemen adalah 0, seperti:
my_list = [["a", "b", 0], ["c", "d", 0], ["e", "f", 0], .....]
Pada awalnya, semua flag adalah 0. Saya menggunakan loop sementara untuk memeriksa apakah setidaknya satu flag elemen adalah 0:
def check(list_):
for item in list_:
if item[2] == 0:
return True
return False
Jika check(my_list)
kembali True
, maka saya terus mengerjakan daftar saya:
while check(my_list):
for item in my_list:
if condition:
item[2] = 1
else:
do_sth()
Sebenarnya, saya ingin menghapus elemen di my_list saat saya mengulanginya, tapi saya tidak diizinkan untuk menghapus item karena saya mengulanginya.
My_list asli tidak memiliki bendera:
my_list = [["a", "b"], ["c", "d"], ["e", "f"], .....]
Karena saya tidak bisa menghapus elemen ketika saya mengulanginya, saya membuat flag-flag ini. Tetapi yang my_list
berisi banyak item, dan while
loop membaca semuanya pada setiap for
loop, dan itu menghabiskan banyak waktu! Apakah Anda punya saran?
sumber
None
atau[]
saat Anda mengulangi daftar alih-alih menghapusnya. Memeriksa seluruh daftar dengan 'check () `iterasi pada semua item sebelum setiap pass pada loop dalam adalah pendekatan yang sangat lambat.Jawaban:
Jawaban terbaik di sini adalah menggunakan
all()
, yang merupakan dasar untuk situasi ini. Kami menggabungkan ini dengan ekspresi generator untuk menghasilkan hasil yang Anda inginkan dengan bersih dan efisien. Sebagai contoh:Catatan yang
all(flag == 0 for (_, _, flag) in items)
secara langsung setara denganall(item[2] == 0 for item in items)
, hanya sedikit lebih baik untuk dibaca dalam hal ini.Dan, untuk contoh filter, pemahaman daftar (tentu saja, Anda bisa menggunakan ekspresi generator yang sesuai):
Jika Anda ingin memeriksa setidaknya satu elemen bernilai 0, opsi yang lebih baik adalah menggunakan
any()
yang lebih mudah dibaca:sumber
all()
danany()
hubungan pendek, jika, misalnya, nilai pertama pada tambang dievaluasiFalse
,all()
akan gagal dan tidak memeriksa nilai lagi, kembaliFalse
. Contoh Anda akan melakukan hal yang sama, kecuali itu akan menghasilkan seluruh daftar perbandingan terlebih dahulu, yang berarti banyak pemrosesan tanpa hasil.Jika Anda ingin memeriksa apakah ada item dalam daftar yang melanggar kondisi, gunakan
all
:Untuk menghapus semua elemen yang tidak cocok, gunakan
filter
sumber
[...]
diall(...)
karena dapat membuat generator bukannya daftar, yang tidak hanya menghemat dua karakter tetapi juga menghemat memori dan waktu. Dengan menggunakan generator, hanya satu item yang akan dihitung pada satu waktu (hasil sebelumnya akan dihapus karena tidak lagi digunakan) dan jika salah satu dari mereka ternyataFalse
, generator akan berhenti menghitung sisanya.Anda dapat menggunakan waktu itertools seperti ini, itu akan berhenti setelah kondisi terpenuhi yang gagal pernyataan Anda. Metode yang berlawanan adalah dropwhile
sumber
Cara lain untuk digunakan
itertools.ifilter
. Ini memeriksa kebenaran dan proses (menggunakanlambda
)Sampel-
sumber
cara ini sedikit lebih fleksibel daripada menggunakan
all()
:atau lebih ringkas:
sumber
all_zeros = False in [x[2] == 0 for x in my_list]
atau bahkan0 in [x[2] for x in my_list]
dan sesuai untukany_zeros
? Saya tidak benar-benar melihat peningkatan luar biasaall()
.all_zeros = False in [x[2] == 0 for x in my_list]
dievaluasi menjadiFalse
, sedangkan versi saya dievaluasiTrue
. Jika Anda mengubahnyaall_zeros = not (False in [x[2] == 0 for x in my_list])
maka setara dengan milikku. Dan0 in [x[2] for x in my_list]
jelas hanya akan berhasilany_zeros
. Tapi saya suka ringkasnya ide Anda, jadi saya akan memperbarui jawaban saya