@ Ivo, kedua pernyataan itu tidak benar. Anda seharusnya tidak pernah memodifikasi daftar yang berulang Anda gunakan for x in listJika Anda menggunakan while loopmaka tidak apa-apa. loop yang ditunjukkan akan menghapus string kosong hingga tidak ada lagi string kosong dan kemudian berhenti. Sebenarnya saya bahkan belum melihat pertanyaan (hanya judulnya) tetapi saya menjawab dengan kemungkinan yang sama persis! Jika Anda tidak ingin menggunakan pemahaman atau filter demi memori, ini adalah solusi yang sangat pythonic.
aaronasterling
4
Masih poin yang sangat valid untuk tidak pernah mengubah daftar yang sudah Anda ulangi :)
Eduard Luca
1
@ EduardLuca jika titik iterasi daftar adalah untuk mengubahnya, maka itu kebalikan dari apa yang harus Anda lakukan. Anda hanya harus berhati-hati agar Anda tahu bahwa Anda tidak menyebabkan perilaku yang tidak terduga dengan melakukannya.
JFA
1
@EduardLuca, @JFA: Intinya adalah dia TIDAK mengulangi daftar apa pun. Dia akan melakukannya jika dia telah menulis sesuatu dalam bentuk for var in list:, tetapi di sini, dia telah menulis while const in list:. yang tidak mengulangi apa pun. itu hanya mengulang kode yang sama sampai suatu kondisi salah.
Jika Anda yang ditekan untuk kinerja, itertool'sifilter bahkan cepat- >>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)2.3468542098999023; >>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)0.04442191123962402.
Humphrey Bogart
4
@ cpburnz Sangat benar. Namun, dengan ifilterhasil dievaluasi dengan malas, tidak sekaligus - saya berpendapat bahwa untuk sebagian besar kasus ifilterlebih baik. Semenarik yang menggunakan filtermasih lebih cepat daripada membungkus sebuah ifilterdalam listsekalipun.
Humphrey Bogart
3
Jika Anda melakukan ini pada daftar angka, perhatikan bahwa nol juga akan dihapus (catatan: Saya hanya menggunakan 3 metode pertama), jadi Anda akan memerlukan metode alternatif.
SnoringFrog
2
Ini hanya berfokus pada kecepatan, bukan pada seberapa pythonic solusinya (pertanyaan yang diajukan). List Comprehensions adalah solusi pythonic, dan filter hanya boleh digunakan jika profiling telah membuktikan bahwa listcomp adalah hambatan.
Tritium21
3
@ siapa pun yang menyebutkan tentang atau menyiratkan-Python-3, harap hanya mengedit dan memperbarui jawabannya. Kami hanya mendiskusikan untuk Python 2 ketika pertanyaan ini diajukan, bahkan Python 3 dirilis hampir 2 tahun. Tetapi perbarui hasil Python 2 dan 3.
livibetter
236
Menggunakan pemahaman daftar adalah cara yang paling Pythonic:
>>> strings =["first","","second"]>>>[x for x in strings if x]['first','second']
Jika daftar harus diubah di tempat, karena ada referensi lain yang harus melihat data yang diperbarui, kemudian gunakan tugas irisan:
Saya suka solusi ini karena mudah beradaptasi. Jika saya perlu untuk menghapus tidak hanya string kosong tapi string yang hanya spasi, misalnya: [x for x in strings if x.strip()].
Obligasi
67
filter sebenarnya memiliki opsi khusus untuk ini:
filter(None, sequence)
Ini akan memfilter semua elemen yang mengevaluasi ke False. Tidak perlu menggunakan callable yang sebenarnya di sini seperti bool, len, dan sebagainya.
itu tidak akan berfungsi jika Anda memiliki ruang di antara untaian kata. misalnya: ['hello world', '', 'hello', '']. >> ['helloworld', '', 'hello', ''] apakah Anda punya solusi lain untuk menjaga jarak di dalam suatu item dalam daftar tetapi menghapus yang lain?
Reihan_amn
Perhatikan bahwa filter(None, lstr)tidak menghapus string kosong dengan spasi' ' Ya, karena itu bukan string kosong.
AMC
15
Balas dari @ Ib33X mengagumkan. Jika Anda ingin menghapus setiap string kosong, setelah dilucuti. Anda perlu menggunakan metode strip juga. Jika tidak, itu akan mengembalikan string kosong juga jika memiliki spasi putih. Seperti, "" juga akan valid untuk jawaban itu. Jadi, bisa diraih oleh.
strings =["first","","second "," "][x.strip()for x in strings if x.strip()]
Jawaban untuk ini adalah ["first", "second"].
Jika Anda ingin menggunakan filtermetode, Anda bisa melakukannya
list(filter(lambda item: item.strip(), strings)). Ini memberikan hasil yang sama.
Alih-alih jika x, saya akan menggunakan jika X! = '' Untuk menghilangkan string kosong. Seperti ini:
str_list =[x for x in str_list if x !='']
Ini akan mempertahankan tipe data Tidak Ada dalam daftar Anda. Juga, jika daftar Anda memiliki bilangan bulat dan 0 adalah satu di antaranya, itu juga akan dipertahankan.
Sebagai contoh,
str_list =[None,'',0,"Hi",'',"Hello"][x for x in str_list if x !=''][None,0,"Hi","Hello"]
Jika daftar Anda memiliki jenis yang berbeda (kecuali Tidak Ada), Anda mungkin memiliki masalah yang lebih besar.
Tritium21
Jenis apa? Saya mencoba dengan int dan tipe numerik lainnya, string, daftar, tupes, set, dan None dan tidak ada masalah di sana. Saya bisa melihat bahwa jika ada tipe yang ditentukan pengguna yang tidak mendukung metode str mungkin memberikan masalah. Haruskah saya khawatir tentang yang lain?
thiruvenkadam
1
Jika Anda memiliki str_list = [None, '', 0, "Hi", '', "Hello"], itu adalah tanda aplikasi yang dirancang dengan buruk. Anda seharusnya tidak memiliki lebih dari satu antarmuka (tipe) dan Tidak Ada dalam daftar yang sama.
Tritium21
3
Mengambil data dari db? daftar argumen untuk suatu fungsi saat melakukan pengujian otomatis?
thiruvenkadam
3
Itu biasanya tupel.
Tritium21
7
Bergantung pada ukuran daftar Anda, mungkin paling efisien jika Anda menggunakan list.remove () daripada membuat daftar baru:
l =["1","","3",""]whileTrue:try:
l.remove("")exceptValueError:break
Ini memiliki keuntungan karena tidak membuat daftar baru, tetapi kerugian karena harus mencari dari awal setiap kali, meskipun tidak seperti menggunakan while '' in lseperti yang diusulkan di atas, itu hanya membutuhkan pencarian sekali per kejadian ''(pasti ada cara untuk menjaga yang terbaik dari kedua metode, tetapi lebih rumit).
Anda dapat mengedit daftar di tempat dengan melakukan ary[:] = [e for e in ary if e]. Jauh lebih bersih dan tidak menggunakan pengecualian untuk aliran kontrol.
Krzysztof Karski
2
Yah, itu tidak benar-benar "di tempat" - Saya cukup yakin ini membuat daftar baru dan hanya menugaskannya ke nama yang lama.
Andrew Jaffe
Ini berkinerja sangat buruk karena ujung data dikocok di memori pada setiap pemindahan. Lebih baik menghapus semua dalam satu pukulan.
wim
7
Ingatlah bahwa jika Anda ingin menjaga spasi putih di dalam string , Anda dapat menghapusnya secara tidak sengaja menggunakan beberapa pendekatan. Jika Anda memiliki daftar ini
['hello world', '', '', 'hello'] apa yang Anda inginkan ['hello world', 'hello']
pertama potong daftar untuk mengkonversi semua jenis ruang putih menjadi string kosong:
space_to_empty =[x.strip()for x in _text_list]
kemudian hapus string kosong dari daftar mereka
space_clean_list =[x for x in space_to_empty if x]
jika Anda ingin menyimpan spasi putih di dalam string, Anda dapat menghapusnya secara tidak sengaja menggunakan beberapa pendekatan. Suka pendekatan ini?
AMC
Terima kasih Bung, itu berhasil untuk saya dengan sedikit perubahan. yaituspace_clean_list = [x.strip() for x in y if x.strip()]
Muhammad Mehran Khan Attari
6
Gunakan filter:
newlist=filter(lambda x: len(x)>0, oldlist)
Kelemahan dari menggunakan filter sebagaimana ditunjukkan adalah bahwa ia lebih lambat daripada alternatif; juga, lambdabiasanya mahal.
Atau Anda bisa menggunakan yang paling sederhana dan paling berulang-ulang:
# I am assuming listtext is the original list containing (possibly) empty itemsfor item in listtext:if item:
newlist.append(str(item))# You can remove str() based on the content of your original list
ini adalah metode yang paling intuitif dan melakukannya dalam waktu yang layak.
Selamat datang di SO. Anda belum diabaikan. Anda belum pernah diserang oleh seorang downvoter yang tidak bersalah. Anda telah diberi umpan balik. Memperkuat: Arg pertama yang Anda usulkan untuk filter lebih buruk daripada lambda x: len(x)yang lebih buruk daripada lambda x : xyang terburuk dari 4 solusi dalam jawaban yang dipilih. Fungsi yang benar lebih disukai, tetapi tidak cukup. Arahkan kursor Anda ke tombol downvote: berbunyi "Jawaban ini tidak berguna".
John Machin
5
Seperti dilansir Aziz Altofilter(None, lstr) tidak menghapus string kosong dengan spasi ' 'tetapi jika Anda yakin lstr hanya berisi string yang dapat Anda gunakanfilter(str.strip, lstr)
Ini hanya berfungsi jika string Anda tidak mengandung spasi. Jika tidak, Anda akan memisahkan string itu juga.
phillyslick
1
@ BenPolinsky seperti yang Anda laporkan joinsolusi akan memisahkan string dengan spasi tetapi filter tidak akan. Terima kasih atas komentar Anda, saya meningkatkan jawaban saya.
Paolo Melchiorre
-1
Ringkas jawaban terbaik:
1. Menghilangkan emtpties TANPA stripping:
Artinya, string semua ruang dipertahankan:
slist = list(filter(None, slist))
PRO:
paling sederhana;
tercepat (lihat tolok ukur di bawah).
2. Untuk menghilangkan kekosongan setelah pengupasan ...
2.a ... saat string TIDAK mengandung spasi di antara kata-kata:
slist =' '.join(slist).split()
PRO:
kode kecil
cepat (TAPI tidak tercepat dengan dataset besar karena memori, bertentangan dengan apa yang hasil @ paolo-melchiorre)
2.b ... kapan string berisi spasi antar kata?
slist = list(filter(str.strip, slist))
PRO:
tercepat;
pemahaman kode.
Patokan pada mesin 2018:
## Build test-data#import random, string
nwords =10000
maxlen =30
null_ratio =0.1
rnd = random.Random(0)# deterministic results
words =[' '* rnd.randint(0, maxlen)if rnd.random()>(1- null_ratio)else''.join(random.choices(string.ascii_letters, k=rnd.randint(0, maxlen)))for _i in range(nwords)]## Test functions#def nostrip_filter(slist):return list(filter(None, slist))def nostrip_comprehension(slist):return[s for s in slist if s]def strip_filter(slist):return list(filter(str.strip, slist))def strip_filter_map(slist):return list(filter(None, map(str.strip, slist)))def strip_filter_comprehension(slist):# waste memoryreturn list(filter(None,[s.strip()for s in slist]))def strip_filter_generator(slist):return list(filter(None,(s.strip()for s in slist)))def strip_join_split(slist):# words without(!) spacesreturn' '.join(slist).split()## Benchmarks#%timeit nostrip_filter(words)142µs ±16.8µs per loop (mean ± std. dev. of 7 runs,10000 loops each)%timeit nostrip_comprehension(words)263µs ±19.1µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter(words)653µs ±37.5µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_map(words)642µs ±36µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_comprehension(words)693µs ±42.2µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_filter_generator(words)750µs ±28.6µs per loop (mean ± std. dev. of 7 runs,1000 loops each)%timeit strip_join_split(words)796µs ±103µs per loop (mean ± std. dev. of 7 runs,1000 loops each)
s and s.strip()dapat disederhanakan menjadi adil s.strip().
AMC
s and s.strip()diperlukan jika kita ingin mereplikasi sepenuhnya filter(None, words), jawaban yang diterima. Saya mengoreksi fungsi sampel x2 di atas dan menjatuhkan x2 yang buruk.
ankostis
-2
Untuk daftar dengan kombinasi spasi dan nilai kosong, gunakan pemahaman daftar sederhana -
>>> s =['I','am','a','','great',' ','',' ','person','!!','Do','you','think','its','a','','a','','joke','',' ','','?','','','','?']
Jadi, Anda bisa lihat, daftar ini memiliki kombinasi spasi dan elemen nol. Menggunakan cuplikan -
>>> d =[x for x in s if x.strip()]>>> d
>>> d =['I','am','a','great','person','!!','Do','you','think','its','a','a','joke','?','?']
for x in list
Jika Anda menggunakanwhile loop
maka tidak apa-apa. loop yang ditunjukkan akan menghapus string kosong hingga tidak ada lagi string kosong dan kemudian berhenti. Sebenarnya saya bahkan belum melihat pertanyaan (hanya judulnya) tetapi saya menjawab dengan kemungkinan yang sama persis! Jika Anda tidak ingin menggunakan pemahaman atau filter demi memori, ini adalah solusi yang sangat pythonic.for var in list:
, tetapi di sini, dia telah menuliswhile const in list:
. yang tidak mengulangi apa pun. itu hanya mengulang kode yang sama sampai suatu kondisi salah.Jawaban:
Saya akan menggunakan
filter
:Python 3 mengembalikan iterator dari
filter
, jadi harus dibungkus dengan panggilan kelist()
sumber
itertool
'sifilter
bahkan cepat->>> timeit('filter(None, str_list)', 'str_list=["a"]*1000', number=100000)
2.3468542098999023
;>>> timeit('itertools.ifilter(None, str_list)', 'str_list=["a"]*1000', number=100000)
0.04442191123962402
.ifilter
hasil dievaluasi dengan malas, tidak sekaligus - saya berpendapat bahwa untuk sebagian besar kasusifilter
lebih baik. Semenarik yang menggunakanfilter
masih lebih cepat daripada membungkus sebuahifilter
dalamlist
sekalipun.Menggunakan pemahaman daftar adalah cara yang paling Pythonic:
Jika daftar harus diubah di tempat, karena ada referensi lain yang harus melihat data yang diperbarui, kemudian gunakan tugas irisan:
sumber
[x for x in strings if x.strip()]
.filter sebenarnya memiliki opsi khusus untuk ini:
Ini akan memfilter semua elemen yang mengevaluasi ke False. Tidak perlu menggunakan callable yang sebenarnya di sini seperti bool, len, dan sebagainya.
Ini sama cepatnya dengan peta (bool, ...)
sumber
Bandingkan waktu
Perhatikan bahwa
filter(None, lstr)
tidak menghapus string kosong dengan spasi' '
, hanya memangkas''
sementara' '.join(lstr).split()
menghilangkan keduanya.Untuk digunakan
filter()
dengan string spasi putih dihapus, dibutuhkan lebih banyak waktu:sumber
filter(None, lstr)
tidak menghapus string kosong dengan spasi' '
Ya, karena itu bukan string kosong.Balas dari @ Ib33X mengagumkan. Jika Anda ingin menghapus setiap string kosong, setelah dilucuti. Anda perlu menggunakan metode strip juga. Jika tidak, itu akan mengembalikan string kosong juga jika memiliki spasi putih. Seperti, "" juga akan valid untuk jawaban itu. Jadi, bisa diraih oleh.
Jawaban untuk ini adalah
["first", "second"]
.Jika Anda ingin menggunakan
filter
metode, Anda bisa melakukannyalist(filter(lambda item: item.strip(), strings))
. Ini memberikan hasil yang sama.sumber
Alih-alih jika x, saya akan menggunakan jika X! = '' Untuk menghilangkan string kosong. Seperti ini:
Ini akan mempertahankan tipe data Tidak Ada dalam daftar Anda. Juga, jika daftar Anda memiliki bilangan bulat dan 0 adalah satu di antaranya, itu juga akan dipertahankan.
Sebagai contoh,
sumber
str_list = [None, '', 0, "Hi", '', "Hello"]
, itu adalah tanda aplikasi yang dirancang dengan buruk. Anda seharusnya tidak memiliki lebih dari satu antarmuka (tipe) dan Tidak Ada dalam daftar yang sama.Bergantung pada ukuran daftar Anda, mungkin paling efisien jika Anda menggunakan list.remove () daripada membuat daftar baru:
Ini memiliki keuntungan karena tidak membuat daftar baru, tetapi kerugian karena harus mencari dari awal setiap kali, meskipun tidak seperti menggunakan
while '' in l
seperti yang diusulkan di atas, itu hanya membutuhkan pencarian sekali per kejadian''
(pasti ada cara untuk menjaga yang terbaik dari kedua metode, tetapi lebih rumit).sumber
ary[:] = [e for e in ary if e]
. Jauh lebih bersih dan tidak menggunakan pengecualian untuk aliran kontrol.Ingatlah bahwa jika Anda ingin menjaga spasi putih di dalam string , Anda dapat menghapusnya secara tidak sengaja menggunakan beberapa pendekatan. Jika Anda memiliki daftar ini
['hello world', '', '', 'hello'] apa yang Anda inginkan ['hello world', 'hello']
pertama potong daftar untuk mengkonversi semua jenis ruang putih menjadi string kosong:
kemudian hapus string kosong dari daftar mereka
sumber
space_clean_list = [x.strip() for x in y if x.strip()]
Gunakan
filter
:Kelemahan dari menggunakan filter sebagaimana ditunjukkan adalah bahwa ia lebih lambat daripada alternatif; juga,
lambda
biasanya mahal.Atau Anda bisa menggunakan yang paling sederhana dan paling berulang-ulang:
ini adalah metode yang paling intuitif dan melakukannya dalam waktu yang layak.
sumber
lambda x: len(x)
yang lebih buruk daripadalambda x : x
yang terburuk dari 4 solusi dalam jawaban yang dipilih. Fungsi yang benar lebih disukai, tetapi tidak cukup. Arahkan kursor Anda ke tombol downvote: berbunyi "Jawaban ini tidak berguna".Seperti dilansir Aziz Alto
filter(None, lstr)
tidak menghapus string kosong dengan spasi' '
tetapi jika Anda yakin lstr hanya berisi string yang dapat Anda gunakanfilter(str.strip, lstr)
Bandingkan waktu di pc saya
Solusi tercepat untuk menghapus
''
dan mengosongkan string dengan spasi' '
tetap ada' '.join(lstr).split()
.Seperti yang dilaporkan dalam komentar situasinya berbeda jika string Anda berisi spasi.
Anda dapat melihat bahwa
filter(str.strip, lstr)
menyimpan string dengan spasi di atasnya tetapi' '.join(lstr).split()
akan membagi string ini.sumber
join
solusi akan memisahkan string dengan spasi tetapi filter tidak akan. Terima kasih atas komentar Anda, saya meningkatkan jawaban saya.Ringkas jawaban terbaik:
1. Menghilangkan emtpties TANPA stripping:
Artinya, string semua ruang dipertahankan:
PRO:
2. Untuk menghilangkan kekosongan setelah pengupasan ...
2.a ... saat string TIDAK mengandung spasi di antara kata-kata:
PRO:
2.b ... kapan string berisi spasi antar kata?
PRO:
Patokan pada mesin 2018:
sumber
s and s.strip()
dapat disederhanakan menjadi adils.strip()
.s and s.strip()
diperlukan jika kita ingin mereplikasi sepenuhnyafilter(None, words)
, jawaban yang diterima. Saya mengoreksi fungsi sampel x2 di atas dan menjatuhkan x2 yang buruk.Untuk daftar dengan kombinasi spasi dan nilai kosong, gunakan pemahaman daftar sederhana -
Jadi, Anda bisa lihat, daftar ini memiliki kombinasi spasi dan elemen nol. Menggunakan cuplikan -
sumber