Membagi dengan koma dan menghapus spasi di Python

346

Saya memiliki beberapa kode python yang terbelah pada koma, tetapi tidak menghapus spasi:

>>> string = "blah, lots  ,  of ,  spaces, here "
>>> mylist = string.split(',')
>>> print mylist
['blah', ' lots  ', '  of ', '  spaces', ' here ']

Saya lebih suka berakhir dengan spasi kosong dihapus seperti ini:

['blah', 'lots', 'of', 'spaces', 'here']

Saya sadar bahwa saya bisa mengulang daftar dan menghapus () setiap item tetapi, karena ini adalah Python, saya menduga ada cara yang lebih cepat, lebih mudah, dan lebih elegan untuk melakukannya.

Mr_Chimp
sumber

Jawaban:

594

Gunakan pemahaman daftar - lebih sederhana, dan mudah dibaca sebagai satu forlingkaran.

my_string = "blah, lots  ,  of ,  spaces, here "
result = [x.strip() for x in my_string.split(',')]
# result is ["blah", "lots", "of", "spaces", "here"]

Lihat: Python docs pada Daftar Pemahaman
Penjelasan daftar yang baik 2 detik.

Sean Vieira
sumber
1
Sangat bagus! Saya menambahkan satu item sebagai berikut untuk menyingkirkan entri daftar kosong. > text = [x.strip () untuk x dalam text.split ('.') jika x! = '']
RandallShanePhD
@Sean: apakah kode python tidak valid / tidak lengkap "maksud asli dari pos" Anda? Menurut ulasan wankers, itu adalah: stackoverflow.com/review/suggested-edits/21504253 . Bisakah Anda memberi tahu mereka sebaliknya dengan membuat koreksi jika mereka salah (lagi)?
Hijauan
Dokumen asli disalin dari REPL (jika saya ingat dengan benar) dan tujuannya adalah memahami konsep yang mendasarinya (menggunakan pemahaman daftar untuk melakukan operasi) - tetapi Anda benar, lebih masuk akal jika Anda melihat daftar pemahaman itu menghasilkan daftar baru.
Sean Vieira
24

Berpisah menggunakan ekspresi reguler. Catatan saya menjadikan case ini lebih umum dengan spasi terkemuka. Pemahaman daftar adalah untuk menghapus string nol di bagian depan dan belakang.

>>> import re
>>> string = "  blah, lots  ,  of ,  spaces, here "
>>> pattern = re.compile("^\s+|\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['blah', 'lots', 'of', 'spaces', 'here']

Ini berfungsi bahkan jika ^\s+tidak cocok:

>>> string = "foo,   bar  "
>>> print([x for x in pattern.split(string) if x])
['foo', 'bar']
>>>

Inilah sebabnya mengapa Anda perlu ^ \ s +:

>>> pattern = re.compile("\s*,\s*|\s+$")
>>> print([x for x in pattern.split(string) if x])
['  blah', 'lots', 'of', 'spaces', 'here']

Lihat ruang terkemuka di bla?

Klarifikasi: di atas menggunakan interpreter Python 3, tetapi hasilnya sama dalam Python 2.

tbc0
sumber
8
Saya percaya [x.strip() for x in my_string.split(',')]lebih pythonic untuk pertanyaan yang diajukan. Mungkin ada kasus di mana solusi saya diperlukan. Saya akan memperbarui konten ini jika saya menemukan satu.
tbc0
Mengapa ^\s+perlu? Saya telah menguji kode Anda tanpa itu dan itu tidak berhasil, tetapi saya tidak tahu mengapa.
laike9m
Jika saya gunakan re.compile("^\s*,\s*$"), hasilnya adalah [' blah, lots , of , spaces, here '].
laike9m
@ laike9m, saya memperbarui jawaban saya untuk menunjukkan kepada Anda perbedaannya. ^\s+membuat. Seperti yang dapat Anda lihat sendiri, ^\s*,\s*$tidak memberikan hasil yang diinginkan. Jadi, jika Anda ingin berpisah dengan regexp, gunakan ^\s+|\s*,\s*|\s+$.
tbc0
Pertandingan pertama kosong jika pola utama (^ \ s +) tidak cocok sehingga Anda mendapatkan sesuatu seperti ['', 'foo', 'bar'] untuk string "foo, bar".
Steeve McCauley
21

Saya datang untuk menambahkan:

map(str.strip, string.split(','))

tetapi melihatnya sudah disebutkan oleh Jason Orendorff dalam komentar .

Membaca komentar Glenn Maynard dalam jawaban yang sama menyarankan daftar pemahaman atas peta saya mulai bertanya-tanya mengapa. Saya berasumsi dia bermaksud untuk alasan kinerja, tapi tentu saja dia mungkin bermaksud untuk alasan gaya, atau sesuatu yang lain (Glenn?).

Jadi tes cepat (mungkin cacat?) Pada kotak saya menerapkan tiga metode dalam satu lingkaran mengungkapkan:

[word.strip() for word in string.split(',')]
$ time ./list_comprehension.py 
real    0m22.876s

map(lambda s: s.strip(), string.split(','))
$ time ./map_with_lambda.py 
real    0m25.736s

map(str.strip, string.split(','))
$ time ./map_with_str.strip.py 
real    0m19.428s

membuat map(str.strip, string.split(',')) pemenang, meskipun tampaknya mereka semua berada di stadion baseball yang sama.

Tentu saja meskipun peta (dengan atau tanpa lambda) tidak harus dikesampingkan karena alasan kinerja, dan bagi saya itu setidaknya sejelas pemahaman daftar.

Edit:

Python 2.6.5 di Ubuntu 10.04

Sean
sumber
15

Hapus saja ruang putih dari string sebelum Anda membaginya.

mylist = my_string.replace(' ','').split(',')
pengguna489041
sumber
10
Jenis masalah jika item yang dipisahkan oleh koma berisi ruang yang disematkan, mis "you just, broke this".
Robert Rossney
1
Ya, -1 untuk ini. Kalian tangguh. Itu memecahkan masalahnya, menyediakan data sampelnya hanya kata-kata tunggal dan tidak ada spesifikasi bahwa data akan menjadi frase. Tapi w / e, kurasa itulah yang kalian lakukan di sini.
user489041
Yah terima kasih, pengguna. Agar adil meskipun saya secara khusus meminta split dan kemudian strip () dan strip menghapus spasi putih terkemuka dan tertinggal dan tidak menyentuh apa pun di antaranya. Namun, sedikit perubahan dan jawaban Anda akan bekerja dengan sempurna: mylist = mystring.strip (). Split (',') walaupun saya tidak tahu apakah ini sangat efisien.
Mr_Chimp
12

Saya tahu ini sudah dijawab, tetapi jika Anda sering melakukan ini, ekspresi reguler mungkin cara yang lebih baik:

>>> import re
>>> re.sub(r'\s', '', string).split(',')
['blah', 'lots', 'of', 'spaces', 'here']

The \scocok dengan karakter spasi, dan kami hanya menggantinya dengan string kosong ''. Anda dapat menemukan info lebih lanjut di sini: http://docs.python.org/library/re.html#re.sub

Brad Montgomery
sumber
3
Contoh Anda tidak akan berfungsi pada string yang berisi spasi. "untuk, contoh ini, satu" akan menjadi "untuk", "contoh", "satu". Tidak mengatakan itu solusi BURUK (ini bekerja dengan baik pada contoh saya) itu hanya tergantung pada tugas yang ada di tangan!
Mr_Chimp
Yap, itu benar sekali! Anda mungkin dapat menyesuaikan regexp sehingga dapat menangani string dengan spasi, tetapi jika pemahaman daftar berfungsi, saya akan mengatakan tetap dengan itu;)
Brad Montgomery
2
import re
result=[x for x in re.split(',| ',your_string) if x!='']

ini berfungsi baik untuk saya.

Zieng
sumber
2

re (seperti pada ekspresi reguler) memungkinkan pemisahan beberapa karakter sekaligus:

$ string = "blah, lots  ,  of ,  spaces, here "
$ re.split(', ',string)
['blah', 'lots  ', ' of ', ' spaces', 'here ']

Ini tidak berfungsi dengan baik untuk string contoh Anda, tetapi berfungsi dengan baik untuk daftar yang dipisahkan dengan koma-ruang. Untuk string contoh Anda, Anda bisa menggabungkan kekuatan re.split untuk membagi pada pola regex untuk mendapatkan efek "split-on-this-or-that".

$ re.split('[, ]',string)
['blah',
 '',
 'lots',
 '',
 '',
 '',
 '',
 'of',
 '',
 '',
 '',
 'spaces',
 '',
 'here',
 '']

Sayangnya, itu jelek, tetapi filterkemauan melakukan trik:

$ filter(None, re.split('[, ]',string))
['blah', 'lots', 'of', 'spaces', 'here']

Voila!

Dannid
sumber
2
Kenapa tidak adil re.split(' *, *', string)?
Paul Tomblin
4
@ PaulTomblin ide bagus. Orang juga dapat melakukan ini: re.split('[, ]*',string)untuk efek yang sama.
Dannid
Dannid saya menyadari setelah menulis bahwa itu tidak menghapus spasi di awal dan akhir seperti jawaban @ tbc0.
Paul Tomblin
@ PaulTomblinheh, dan bantahan saya [, ]*meninggalkan string kosong di akhir daftar. Saya pikir filter masih merupakan hal yang bagus untuk dilemparkan ke sana, atau tetap pada daftar pemahaman seperti jawaban teratas tidak.
Dannid
1

map(lambda s: s.strip(), mylist)akan sedikit lebih baik daripada perulangan secara eksplisit. Atau untuk semuanya sekaligus:map(lambda s:s.strip(), string.split(','))

pengguna470379
sumber
10
Kiat: setiap kali Anda menemukan diri Anda menggunakan map, terutama jika Anda menggunakannya lambda, periksa ulang untuk melihat apakah Anda harus menggunakan pemahaman daftar.
Glenn Maynard
11
Anda dapat menghindari lambda dengan map(str.strip, s.split(',')).
Jason Orendorff
1
s = 'bla, buu, jii'

sp = []
sp = s.split(',')
for st in sp:
    print st
Parikshit Pandya
sumber
1
import re
mylist = [x for x in re.compile('\s*[,|\s+]\s*').split(string)]

Cukup, koma atau setidaknya satu spasi putih dengan / tanpa mendahului / menggantikan spasi putih.

Tolong coba!

GyuHyeon Choi
sumber
0

map(lambda s: s.strip(), mylist)akan sedikit lebih baik daripada perulangan secara eksplisit.
Atau untuk semuanya sekaligus:

map(lambda s:s.strip(), string.split(','))

Itu pada dasarnya semua yang Anda butuhkan.

DJbigpenis
sumber