Cara terbaik untuk menentukan spasi putih dalam operasi String.Split

243

Saya memisahkan string berdasarkan spasi putih sebagai berikut:

string myStr = "The quick brown fox jumps over the lazy dog";

char[] whitespace = new char[] { ' ', '\t' };
string[] ssizes = myStr.Split(whitespace);

Sangat menjengkelkan untuk mendefinisikan array char [] di mana-mana dalam kode saya, saya ingin melakukan ini. Apakah ada cara yang lebih efisien yang tidak memerlukan pembuatan array karakter (yang rawan kesalahan jika disalin di tempat yang berbeda)?

John Saunders
sumber
1
melakukan ini: myStr.Split (''); tidak bekerja?
woolagaroo
4
Jika saya mengerti ini dengan benar, ini hanya akan mencari ruang, bukan ruang kosong generik
Lihat juga kemungkinan duplikat, tetapi jawaban ini nanti memiliki SplitStringOptions. stackoverflow.com/questions/1562981/…
selamat tinggal

Jawaban:

469

Jika Anda baru saja menelepon:

string[] ssize = myStr.Split(null);

atau:

string[] ssize = myStr.Split(new char[0]);

maka white-space diasumsikan sebagai karakter pemisah. Dari string.Split(char[])halaman dokumentasi metode .

Jika parameter pemisah adalah nullatau tidak mengandung karakter, karakter spasi-putih diasumsikan sebagai pembatas. Karakter white-space didefinisikan oleh standar Unicode dan kembali truejika dilewatkan ke Char.IsWhiteSpacemetode.

Selalu, selalu, selalu baca dokumentasi!

jason
sumber
2
Masalah dengan pemisahan oleh spasi putih adalah jika Anda harus menyatukannya kembali, Anda tidak tahu karakter spasi mana yang harus dimasukkan kembali.
Ross Presser
19
(char[])nullsedikit lebih baik karena menghindari membuat objek baru. (Anda tidak dapat menggunakan nulldengan optionskelebihan apa pun ).
Artfunkel
5
@RossPresser: Menyatukan kembali string adalah masalah yang sama sekali berbeda, jadi saya tidak akan mengatakan ini adalah masalah di sini. Tetapi jika semua yang perlu Anda lakukan adalah meletakkan kembali string persis seperti sebelumnya, maka mungkin lebih baik simpan saja yang asli.
stakx - tidak lagi berkontribusi
4
Pertanyaan bodoh, tetapi jika Anda menggunakan null, apakah Anda masih perlu menentukan StringSplitOption.RemoveEmptyEntriesatau mereka diabaikan secara default?
yu_ominae
2
@RossPresser: Karena String.Split tidak menyediakan mekanisme apa pun untuk melacak karakter yang digunakan untuk memisahkan string, pengamatan Anda tidak relevan: seseorang tidak dapat mencapai apa yang Anda cari menggunakan String.Split, sehingga memerlukan T&J yang berbeda.
ToolmakerSteve
207

Ya, perlu ada satu jawaban lagi di sini!

Semua solusi sejauh ini menangani domain input kanonik yang agak terbatas , dengan kecerdasan: akarakter spasi putih tunggal antara elemen (meskipun ujung topi untuk @cherno untuk setidaknya menyebutkan masalah). Tapi saya sampaikan bahwa dalam semua kecuali skenario yang paling tidak jelas, pemisahan semua ini akan menghasilkan hasil yang identik:

string myStrA = "The quick brown fox jumps over the lazy dog";
string myStrB = "The  quick  brown  fox  jumps  over  the  lazy  dog";
string myStrC = "The quick brown fox      jumps over the lazy dog";
string myStrD = "   The quick brown fox jumps over the lazy dog";

String.Split(dalam salah satu rasa yang ditunjukkan di seluruh jawaban lain di sini) tidak berfungsi dengan baik kecuali jika Anda melampirkan RemoveEmptyEntriespilihan dengan salah satu dari ini:

myStr.Split(new char[0], StringSplitOptions.RemoveEmptyEntries)
myStr.Split(new char[] {' ','\t'}, StringSplitOptions.RemoveEmptyEntries)

Seperti yang diungkapkan oleh ilustrasi, menghilangkan opsi menghasilkan empat hasil yang berbeda (berlabel A, B, C, dan D) vs. hasil tunggal dari keempat input ketika Anda menggunakan RemoveEmptyEntries:

String.Split vs Regex.Split

Tentu saja, jika Anda tidak suka menggunakan opsi, cukup gunakan alternatif regex :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)
Michael Sorens
sumber
4
Saya pikir, @RossPresser, bahwa hal itu tercakup oleh kualifikasi saya "di bawah semua kecuali skenario yang paling tidak jelas" karena bahkan ketika ingin menggabungkan kembali elemen-elemen saya akan kesulitan untuk memiliki kasus di mana saya peduli tentang banyak ruang. Saya ingin bentuk kanonik - satu ruang antara masing-masing. Jadi saya dengan hormat tidak setuju - itu akan "jarang salah" daripada "biasanya salah".
Michael Sorens
1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser
3
Jika Anda benar-benar berpikir bahwa ini tidak jelas, maka saya kira kita harus setuju untuk tidak setuju, tetapi jika saya meninggalkan fungsi ini dari perangkat lunak saya, saya akan kehilangan pekerjaan saya. Pengguna menyukai konten mereka agar terlihat seperti yang mereka inginkan.
Ross Presser
4
Ini harus menjadi jawaban yang diterima, karena jauh lebih lengkap.
Dennis
1
Saya bertanya-tanya mengapa Anda menambahkan .Where(s => s != string.Empty)ke Regex. Karena Anda menentukan \s+(jumlah spasi), tidak ada item kosong di antaranya.
Jack Miller
44

Menurut dokumentasi :

Jika parameter pemisah adalah nol atau tidak mengandung karakter, karakter spasi-putih diasumsikan sebagai pembatas. Karakter spasi putih ditentukan oleh standar Unicode dan mengembalikan true jika dilewatkan ke metode Char.IsWhiteSpace.

Jadi panggil saja myStr.Split();Tidak perlu lewat apa pun karena pemisah adalah paramsarray.

ageektrapped
sumber
11

Kenapa tidak Anda gunakan ?:

string[] ssizes = myStr.Split(' ', '\t');
Renatas M.
sumber
2
Tidak ada Split overload yang membutuhkan dua karakter.
takrl
1
@takrl: Lihat di sini public string [] Split (params char [] separator) .NET v2
Renatas M.
Ya, ini membutuhkan array karakter. Cuplikan kode Anda melewati dua karakter tunggal.
takrl
15
@takrl: apakah Anda tahu apa kata kunci params ???
Renatas M.
Cukup keren, +1 untuk itu. Mungkin orang yang turun jabatan juga tidak tahu.
takrl
3

Perhatikan bahwa spasi putih yang berdekatan TIDAK akan diperlakukan sebagai pembatas tunggal, bahkan ketika menggunakan String.Split(null) . Jika salah satu token Anda dipisahkan dengan beberapa spasi atau tab, Anda akan mendapatkan string kosong yang dikembalikan dalam array Anda.

Dari dokumentasi:

Setiap elemen pemisah mendefinisikan karakter pembatas yang terpisah. Jika dua pembatas berbatasan, atau pembatas ditemukan di awal atau akhir dari contoh ini, elemen array yang sesuai berisi Kosong.

cherno
sumber
2

Jadi jangan salin dan tempel! Ekstrak fungsi untuk melakukan pemisahan dan menggunakannya kembali.

public static string[] SplitWhitespace (string input)
{
    char[] whitespace = new char[] { ' ', '\t' };
    return input.Split(whitespace);
}

Penggunaan kembali kode adalah teman Anda.

Tim Rogers
sumber
1

kamu bisa memakai

var FirstString = YourString.Split (). First ();

untuk membagi string.

Haxer
sumber
0

Tidak bisakah kau melakukannya inline?

var sizes = subject.Split(new char[] { ' ', '\t' });

Jika tidak, jika Anda sering melakukan hal ini, Anda selalu dapat membuat konstanta atau sesuatu yang berisi array arang.

Seperti yang telah dicatat orang lain, Anda dapat menggunakan dokumentasi nullatau menggunakan array kosong sesuai dengan dokumentasi . Ketika Anda melakukannya, ia akan menggunakan karakter spasi putih secara otomatis.

var sizes = subject.Split(null);
Svish
sumber
0

Jika mengulangi kode yang sama adalah masalahnya, tulis metode ekstensi pada kelas String yang merangkum logika pemisahan.

Xhalent
sumber
1
Ini tidak benar-benar menjawab pertanyaan, maaf.
p.campbell
hal. campbell: Ya, itu: OP meminta solusi yang tidak perlu menyalin array karakter di mana-mana. Solusi yang jelas adalah membuat fungsi untuk melakukan tugas. Jawaban ini menunjukkan bahwa fungsi seperti itu bisa menjadi metode ekstensi. (Jawabannya dapat ditingkatkan, dengan menunjukkan kode untuk melakukannya ...)
ToolmakerSteve