Найкращий спосіб вказати пробіл в операції 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або не містить символів, то роздільниками вважаються символи пробілу. Символи пробілу визначаються стандартом Unicode і повертаються, trueякщо вони передані Char.IsWhiteSpaceметоду.

Завжди, завжди, завжди читайте документацію!


2
Проблема з розщепленням пробілів полягає в тому, що якщо вам доведеться скласти його знову, ви не знаєте, який символ пробілу потрібно повернути назад.
Росс Пресер

19
(char[])nullтрохи краще, оскільки це дозволяє уникнути створення нового об’єкта. (Ви не можете використовувати nullжодну з optionsперевантажень).
Artfunkel

5
@RossPresser: З'єднання рядків разом - це зовсім інша проблема, тому я б не сказав, що це проблема тут. Але якщо все, що вам потрібно зробити, це скласти рядок назад, як саме було раніше, то, можливо, краще просто зберегти оригінал.
stakx - більше не вносяться повідомлення

4
Дурне запитання, але якщо ви користуєтесь null, чи все-таки потрібно вказати StringSplitOption.RemoveEmptyEntriesабо вони за замовчуванням ігноруються?
yu_ominae

2
@RossPresser: Оскільки String.Split не забезпечує жодного механізму для відстеження символів, які використовуються для розділення рядка, ваше спостереження не має значення: не можна досягти того, що ви шукаєте за допомогою String.Split, так що для цього потрібні різні запитання та відповіді.
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.Split(myStr, @"\s+").Where(s => s != string.Empty)

4
Я думаю, @RossPresser, що це стосується мого класифікатора "за всіма, але найбільш незрозумілими сценаріями", тому що навіть при бажанні рекомбінувати елементи, я б сильно натиснув, щоб мати випадок, коли я дбаю про декілька пробілів. Я хотів би канонічної форми - один пробіл між кожним. Тож я з повагою не погоджуюся - це було б "рідко неправильно", а не "зазвичай неправильно".
Майкл Соренс

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

3
Якщо ви справді вважаєте, що це незрозуміло, то, мабуть, нам доведеться погодитися не погодитися, але якби я залишив цю функцію поза моїм програмним забезпеченням, я втратив би роботу. Користувачам подобається, що їх вміст виглядає так, як вони хочуть.
Росс Пресер

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: Подивіться тут public string [] Спліт (params char [] separator) .NET v2
Renatas M.

Так, для цього потрібен масив символів. Ваш фрагмент коду передає два окремих символи.
takrl

15
@takrl: ви знаєте , що PARAMS ключове слово ???
Ренатас М.

Досить круто, +1 за це. Напевно, людина, яка прихилилася, теж не знала.
takrl

3

Зауважте, що сусідні пробіли НЕ розглядаються як окремий роздільник, навіть при використанні String.Split(null). Якщо будь-який з ваших жетонів розділений декількома пробілами чи вкладками, ви отримаєте порожні рядки у своєму масиві.

З документації:

Кожен елемент роздільника визначає окремий розділовий символ. Якщо два роздільники є сусідніми, або розмежувач знайдений на початку або в кінці цього примірника, відповідний елемент масиву містить порожній.


2

Тому не копіюйте та не вставляйте! Витягніть функцію, щоб зробити ваш розщеплення і повторно використовувати його.

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

Повторне використання коду - ваш друг.



1

ви можете використовувати

var FirstString = YourString.Split (). Перший ();

розділити рядок.


0

Хіба ти не можеш це зробити в порядку?

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

В іншому випадку, якщо ви робите цю точну річ часто, ви завжди можете створити константу або щось, що містить цей масив знаків.

Як зазначають інші, ви можете, згідно з документацією, використовувати nullтакож порожній масив. Коли ви це зробите, він автоматично використовуватиме символи пробілу.

var sizes = subject.Split(null);

0

Якщо повторення того ж коду є проблемою, напишіть метод розширення для класу String, який інкапсулює логіку розщеплення.


1
Це насправді не відповідає на питання, вибачте.
p.campbell

p. Кемпбелл: Так, так: OP попросив рішення, яке не потребує копіювання масиву символів скрізь. Очевидним рішенням є створення функції для виконання завдання. Ця відповідь вказує, що така функція може бути методом розширення. (Відповідь можна покращити, показавши код для цього ...)
ToolmakerSteve

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.