Найкращий спосіб вказати пробіл в операції 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.