วิธีที่ดีที่สุดในการระบุช่องว่างในการดำเนินงาน String.Split


243

ฉันกำลังแยกสตริงตามช่องว่างดังนี้:

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

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

มันเป็นเรื่องที่น่ากลัวที่จะกำหนด char [] ทุกที่ในรหัสของฉันฉันต้องการทำ มีวิธีที่มีประสิทธิภาพมากกว่าที่ไม่ต้องการการสร้างอาร์เรย์อักขระ (ซึ่งมีแนวโน้มที่จะเกิดข้อผิดพลาดหากคัดลอกในที่ต่าง ๆ ) หรือไม่?


1
ทำสิ่งนี้: myStr.Split (''); ไม่ทำงาน?
woolagaroo

4
หากฉันเข้าใจสิ่งนี้อย่างถูกต้องสิ่งนี้จะค้นหาช่องว่างไม่ใช่ช่องว่างทั่วไป

ดูซ้ำซ้อนที่เป็นไปได้ แต่คำตอบในภายหลังเหล่านี้มี SplitStringOptions stackoverflow.com/questions/1562981/…
goodeye

คำตอบ:


469

หากคุณเพิ่งโทร:

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

หรือ:

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

จากนั้นช่องว่างสีขาวจะถือว่าเป็นอักขระที่แยก จากหน้าเอกสารประกอบของวิธีการstring.Split(char[])

หากพารามิเตอร์ตัวคั่นคือnullหรือไม่มีอักขระอักขระ white-space จะถือว่าเป็นตัวคั่น อักขระช่องว่างถูกกำหนดโดยมาตรฐาน Unicode และส่งคืนtrueถ้าส่งผ่านไปยังChar.IsWhiteSpaceเมธอด

เสมออ่านเอกสารเสมอ !


2
ปัญหาในการแยกโดยช่องว่างคือถ้าคุณต้องรวบรวมมันอีกครั้งคุณไม่ทราบว่าอักขระช่องว่างที่จะนำกลับมา
Ross Presser

19
(char[])nullจะดีกว่าเล็กน้อยเนื่องจากจะเป็นการหลีกเลี่ยงการสร้างวัตถุใหม่ (คุณไม่สามารถใช้nullกับการoptionsโอเวอร์โหลดใด ๆ)
Artfunkel

5
@RossPresser: การใส่สายอักขระเข้าด้วยกันเป็นปัญหาที่แตกต่างไปจากเดิมอย่างสิ้นเชิงดังนั้นฉันจะไม่พูดว่านี่เป็นปัญหาที่นี่ แต่ถ้าสิ่งที่คุณต้องทำคือใส่สายกลับมารวมกันอย่างที่มันเคยเป็นมาก่อนบางทีอาจจะดีกว่าแค่เก็บต้นฉบับไว้
stakx - ไม่สนับสนุนอีก

4
คำถามงี่เง่า แต่ถ้าคุณใช้nullคุณยังจำเป็นต้องระบุStringSplitOption.RemoveEmptyEntriesหรือไม่โดยค่าเริ่มต้นหรือไม่
yu_ominae

2
@RossPresser: เนื่องจาก String.Split ไม่มีกลไกใด ๆ ในการติดตามตัวอักษรที่ใช้ในการแยกสตริงการสังเกตของคุณจึงไม่เกี่ยวข้อง: เราไม่สามารถบรรลุสิ่งที่คุณต้องการโดยใช้ String.Split ดังนั้นจึงต้องใช้ Q&A ที่แตกต่างกัน
ToolmakerSteve

207

ใช่จำเป็นต้องมีคำตอบอีกหนึ่งข้อที่นี่!

การแก้ปัญหาทั้งหมดจึงอยู่ที่โดเมนที่ค่อนข้าง จำกัด ของการป้อนข้อมูลที่เป็นที่ยอมรับเพื่อปัญญา: ตัวละครช่องว่างเดียวระหว่างองค์ประกอบ (แม้ว่าปลายหมวกถึง @cherno อย่างน้อยพูดถึงปัญหา) แต่ฉันส่งสิ่งนั้นในสถานการณ์ที่ไม่ชัดเจนส่วนใหญ่การแบ่งสิ่งเหล่านี้ควรให้ผลลัพธ์ที่เหมือนกัน:

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(ในรสชาติใด ๆ ที่แสดงตลอดคำตอบอื่น ๆ ที่นี่) ก็ใช้งานได้ไม่ดีเว้นแต่คุณจะแนบRemoveEmptyEntriesตัวเลือกด้วย:

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

ดังที่ภาพประกอบแสดงให้เห็นการละเว้นตัวเลือกจะให้ผลลัพธ์ที่แตกต่างกันสี่แบบ (ติดป้าย A, B, C และ D) กับผลลัพธ์เดี่ยวจากอินพุตทั้งสี่เมื่อคุณใช้RemoveEmptyEntries:

String.Split vs Regex.Split

แน่นอนถ้าคุณไม่ชอบใช้ตัวเลือกเพียงใช้ทางเลือก regex :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)

4
ฉันคิดว่า @RossPresser ที่ครอบคลุมโดยผู้คัดเลือกของฉัน "ภายใต้สถานการณ์ทั้งหมด แต่คลุมเครือที่สุด" เพราะแม้ในขณะที่ต้องการรวมองค์ประกอบอีกครั้งฉันก็จะกดยากที่จะมีกรณีที่ฉันสนใจพื้นที่หลายแห่ง ฉันต้องการรูปแบบบัญญัติ - หนึ่งช่องว่างระหว่างกัน ดังนั้นฉันจึงไม่เห็นด้วยอย่างเคารพ - มันจะเป็น "ไม่ค่อยผิด" มากกว่า "มักจะผิด"
Michael Sorens

1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser

3
หากคุณคิดว่านี่เป็นสิ่งที่คลุมเครือจริง ๆ ฉันคิดว่าเราจะต้องเห็นด้วยที่จะไม่เห็นด้วย แต่ถ้าฉันออกจากฟังก์ชั่นนี้จากซอฟต์แวร์ของฉันฉันจะสูญเสียงานของฉัน ผู้ใช้ชื่นชอบเนื้อหาของพวกเขาเพื่อดูในแบบที่พวกเขาต้องการให้มันดู
Ross Presser

4
นี่ควรเป็นคำตอบที่ได้รับการยอมรับเพราะมันสมบูรณ์มากกว่า
เดนนิส

1
ฉันสงสัยว่าทำไมคุณเพิ่ม.Where(s => s != string.Empty)ไปยัง Regex เนื่องจากคุณระบุ\s+(จำนวนช่องว่างใด ๆ ) จึงไม่มีรายการว่างในระหว่างนั้น
แจ็คมิลเลอร์

44

ตามเอกสาร :

หากพารามิเตอร์ตัวคั่นเป็นโมฆะหรือไม่มีอักขระอักขระสีขาวช่องว่างจะถือว่าเป็นตัวคั่น อักขระช่องว่างถูกกำหนดโดยมาตรฐาน Unicode และคืนค่าจริงถ้าส่งผ่านไปยังวิธี Char.IsWhiteSpace

ดังนั้นแค่โทรmyStr.Split();ไม่จำเป็นต้องผ่านอะไรเลยเพราะตัวคั่นเป็นparamsอาร์เรย์


11

ทำไมคุณไม่ใช้:

string[] ssizes = myStr.Split(' ', '\t');

2
ไม่มีการโอเวอร์โหลดแบบแยกที่ใช้เวลาสองตัวอักษร
takrl

1
@takrl: ดูที่นี่สตริงสาธารณะ [] แยก (params ถ่าน [] ตัวคั่น). NET v2
Renatas M.

ใช่มันต้องใช้อาร์เรย์ของตัวละคร ข้อมูลโค้ดของคุณมีความยาวอักขระสองตัว
takrl

15
@takrl: คุณรู้หรือไม่ว่าคำหลักparamsคืออะไร ???
Renatas M.

ค่อนข้างเท่ +1 สำหรับสิ่งนั้น อาจเป็นคนที่ downvoted ไม่ทราบเช่นกัน
takrl

3

String.Split(null)โปรดทราบว่าช่องว่างที่อยู่ติดกันจะไม่ได้รับการปฏิบัติเป็นตัวคั่นเดียวแม้เมื่อมีการใช้ หากโทเค็นใด ๆ ของคุณถูกคั่นด้วยช่องว่างหรือหลายแท็บคุณจะได้รับสตริงว่างกลับมาในอาร์เรย์ของคุณ

จากเอกสาร:

องค์ประกอบของตัวคั่นแต่ละตัวจะกำหนดอักขระตัวคั่นแยกต่างหาก หากตัวคั่นสองตัวติดกันหรือพบตัวคั่นที่จุดเริ่มต้นหรือจุดสิ้นสุดของอินสแตนซ์นี้องค์ประกอบอาเรย์ที่สอดคล้องกันจะมีค่าว่าง


2

ดังนั้นอย่าคัดลอกและวาง! แยกฟังก์ชั่นเพื่อแยกและนำมาใช้ซ้ำ

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

การใช้รหัสซ้ำคือเพื่อนของคุณ


1

ทำไมคุณไม่ทำเช่นนี้:

var ssizes = myStr.Split(" \t".ToCharArray());

ดูเหมือนว่ามีวิธีการString.ToCharArray()ใน. NET 4.0!

แก้ไข:ตาม VMAtm ได้ชี้ให้เห็นวิธีการที่มีอยู่แล้วใน. NET 2.0!


วิธีนี้อยู่ใน. NET 2.0 !!! msdn.microsoft.com/en-us/library/ezftk57x(VS.80).aspx
VMAtm


0

คุณไม่สามารถทำแบบอินไลน์ได้หรือ

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

มิฉะนั้นถ้าคุณทำสิ่งนี้บ่อยๆคุณสามารถสร้างค่าคงที่หรือสิ่งที่มีอาร์เรย์อักขระนั้น

ในฐานะที่เป็นคนอื่นได้ระบุไว้คุณสามารถตามเอกสารยังใช้nullหรืออาร์เรย์ที่ว่างเปล่า เมื่อคุณทำเช่นนั้นมันจะใช้อักขระช่องว่างโดยอัตโนมัติ

var sizes = subject.Split(null);

0

หากการทำซ้ำรหัสเดียวกันเป็นปัญหาให้เขียนวิธีการขยายบนคลาส String ที่สรุปการแยกตรรกะ


1
สิ่งนี้ไม่ได้ตอบคำถามจริงๆขออภัย
p.campbell

พี แคมป์เบลล์: ใช่: OP ขอวิธีแก้ปัญหาที่ไม่ต้องการคัดลอกอาเรย์ตัวละครทุกที่ ทางออกที่ชัดเจนคือการสร้างฟังก์ชั่นในการทำงาน คำตอบนี้ชี้ให้เห็นว่าฟังก์ชั่นดังกล่าวอาจเป็นวิธีการขยาย (คำตอบอาจได้รับการปรับปรุงโดยแสดงรหัสให้ทำ ... )
ToolmakerSteve

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.