Cách tốt nhất để chỉ định khoảng trắng trong hoạt động String.Split


242

Tôi đang phân tách một chuỗi dựa trên khoảng trắng như sau:

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

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

Thật khó để định nghĩa mảng char [] ở mọi nơi trong mã của tôi, tôi muốn làm điều này. Có cách nào hiệu quả hơn mà không yêu cầu tạo mảng ký tự (dễ bị lỗi nếu được sao chép ở những nơi khác nhau) không?


1
thực hiện điều này: myStr.Split (''); không làm việc?
Woolagaroo

4
Nếu tôi hiểu điều này một cách chính xác thì điều này sẽ chỉ tìm kiếm một khoảng trắng, không phải khoảng trắng chung

Cũng có thể trùng lặp, nhưng những câu trả lời sau này có SplitStringOptions. stackoverflow.com/questions/1562981/ từ
goodeye

Câu trả lời:


469

Nếu bạn chỉ gọi:

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

hoặc là:

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

sau đó khoảng trắng được coi là ký tự phân tách. Từ string.Split(char[])trang tài liệu của phương pháp .

Nếu tham số dấu phân cách là nullhoặc không chứa ký tự, các ký tự khoảng trắng được coi là dấu phân cách. Các ký tự khoảng trắng được xác định theo tiêu chuẩn Unicode và trả về truenếu chúng được truyền cho Char.IsWhiteSpacephương thức.

Luôn luôn, luôn luôn, luôn luôn đọc tài liệu!


2
Rắc rối với việc phân tách bằng khoảng trắng là nếu bạn phải đặt nó lại với nhau, bạn không biết nên đặt ký tự khoảng trắng nào.
Ross Presser

19
(char[])nulltốt hơn một chút vì nó tránh tạo ra một đối tượng mới. (Bạn không thể sử dụng nullvới bất kỳ sự optionsquá tải nào).
Artfunkel

5
@RossPresser: Đặt một chuỗi lại với nhau là một vấn đề hoàn toàn khác, vì vậy tôi sẽ không nói đây là một vấn đề ở đây. Nhưng nếu tất cả những gì bạn cần làm là đặt chuỗi lại với nhau chính xác như trước đây, thì có lẽ tốt hơn là giữ nguyên bản gốc.
stakx - không còn đóng góp vào

4
Câu hỏi ngu ngốc, nhưng nếu bạn sử dụng null, bạn vẫn cần chỉ định StringSplitOption.RemoveEmptyEntrieshoặc chúng bị bỏ qua theo mặc định?
yu_ominae

2
@RossPresser: Vì String.Split không cung cấp bất kỳ cơ chế nào để theo dõi các ký tự được sử dụng để phân tách chuỗi, nên việc quan sát của bạn không liên quan: người ta không thể đạt được những gì bạn tìm kiếm khi sử dụng String.Split, do đó cần có Hỏi & Đáp khác.
ToolmakerSteve

207

Vâng, cần có thêm một câu trả lời ở đây!

Do đó, tất cả các giải pháp đều giải quyết được miền hạn chế của đầu vào chính tắc , để dí dỏm: một ký tự khoảng trắng duy nhất giữa các phần tử (mặc dù phần chóp mũ cho @cherno ít nhất là đề cập đến vấn đề). Nhưng tôi gửi rằng trong tất cả các tình huống khó hiểu nhất, việc tách tất cả các kịch bản này sẽ mang lại kết quả giống hệt nhau:

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(trong bất kỳ hương vị nào được hiển thị trong các câu trả lời khác ở đây) đơn giản là không hoạt động tốt trừ khi bạn đính kèm RemoveEmptyEntriestùy chọn với một trong hai cách sau:

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

Như hình minh họa cho thấy, bỏ qua tùy chọn mang lại bốn kết quả khác nhau (được gắn nhãn A, B, C và D) so với kết quả duy nhất từ ​​cả bốn đầu vào khi bạn sử dụng RemoveEmptyEntries:

Chuỗi.Split vs Regex.Split

Tất nhiên, nếu bạn không thích sử dụng các tùy chọn, chỉ cần sử dụng thay thế regex :-)

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

4
Tôi nghĩ, @RossPresser, được bao phủ bởi vòng loại của tôi "trong tất cả các tình huống khó hiểu nhất" bởi vì ngay cả khi muốn kết hợp lại các yếu tố tôi sẽ khó có thể gặp trường hợp tôi quan tâm đến nhiều không gian. Tôi muốn có một hình thức kinh điển - một không gian giữa mỗi. Vì vậy, tôi tôn trọng không đồng ý - nó sẽ "hiếm khi sai" thay vì "thường sai".
Michael Sorens

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

3
Nếu bạn thực sự nghĩ rằng điều này là tối nghĩa, thì tôi đoán chúng ta sẽ phải đồng ý không đồng ý, nhưng nếu tôi bỏ chức năng này ra khỏi phần mềm thì tôi sẽ mất việc. Người dùng thích nội dung của họ để nhìn theo cách họ muốn.
Ross Presser

4
Đây phải là một câu trả lời được chấp nhận, vì nó đầy đủ hơn nhiều.
Dennis

1
Tôi tự hỏi tại sao bạn thêm vào .Where(s => s != string.Empty)Regex. Vì bạn chỉ định \s+(bất kỳ số lượng khoảng trắng) nên không thể có mục trống ở giữa.
Jack Miller

44

Theo tài liệu :

Nếu tham số dấu tách là null hoặc không chứa ký tự, các ký tự khoảng trắng được coi là dấu phân cách. Các ký tự khoảng trắng được xác định theo tiêu chuẩn Unicode và trả về giá trị true nếu chúng được truyền cho phương thức Char.IsWhiteSpace.

Vì vậy, chỉ cần gọi myStr.Split();Không cần phải vượt qua bất cứ điều gì vì dấu phân cách là một paramsmảng.


11

Tại sao bạn không sử dụng?:

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

2
Không có quá tải Split mất hai ký tự.
takrl

1
@takrl: Xem ở đây chuỗi công khai [] Split (params char [] separator) .NET v2
Renatas M.

Vâng, điều này có một mảng ký tự. Đoạn mã của bạn vượt qua hai ký tự đơn.
takrl

15
@takrl: bạn có biết từ khóa params là gì không ???
Renatas M.

Khá tuyệt, +1 cho điều đó. Có lẽ người bị đánh giá thấp cũng không biết.
takrl

3

Lưu ý rằng khoảng trắng liền kề sẽ KHÔNG được coi là một dấu phân cách duy nhất, ngay cả khi sử dụng String.Split(null). Nếu bất kỳ mã thông báo nào của bạn được phân tách bằng nhiều khoảng trắng hoặc tab, bạn sẽ nhận được các chuỗi trống được trả về trong mảng của mình.

Từ tài liệu:

Mỗi phần tử của dấu phân cách xác định một ký tự phân cách riêng. Nếu hai dấu phân cách liền kề hoặc một dấu phân cách được tìm thấy ở đầu hoặc cuối của thể hiện này, phần tử mảng tương ứng chứa rỗng.


2

Vì vậy, đừng sao chép và dán! Trích xuất một chức năng để thực hiện việc phân tách của bạn và tái sử dụng nó.

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

Tái sử dụng mã là bạn của bạn.



1

bạn có thể dùng

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

để tách chuỗi.


0

Bạn không thể làm điều đó nội tuyến?

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

Mặt khác, nếu bạn làm điều này chính xác thường xuyên, bạn luôn có thể tạo hằng số hoặc thứ gì đó chứa mảng char đó.

Như những người khác đã lưu ý bạn có thể theo tài liệu cũng sử dụng nullhoặc một mảng trống. Khi bạn làm điều đó nó sẽ sử dụng các ký tự khoảng trắng tự động.

var sizes = subject.Split(null);

0

Nếu lặp lại cùng một mã là vấn đề, hãy viết một phương thức mở rộng trên lớp String đóng gói logic tách.


1
Điều này không thực sự trả lời câu hỏi, xin lỗi.
p.campbell

tr. campbell: Có, OP yêu cầu một giải pháp không yêu cầu sao chép mảng ký tự ở mọi nơi. Một giải pháp rõ ràng là tạo ra một chức năng để thực hiện nhiệm vụ. Câu trả lời này chỉ ra rằng một hàm như vậy có thể là một phương thức mở rộng. (Câu trả lời có thể được cải thiện, bằng cách hiển thị mã để làm như vậy ...)
ToolmakerSteve

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.