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.

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.


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.


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


15

Hapus saja ruang putih dari string sebelum Anda membaginya.

mylist = my_string.replace(' ','').split(',')

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


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.


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!


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(','))


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
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!


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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.