Лучший способ указать пробел в операции 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перегрузок).
— Артфункель

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 против Regex.Split

Конечно, если вам не нравится использование опций, просто используйте альтернативу регулярному выражению :-)

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

4
Я думаю, @RossPresser, что это покрыто моим классификатором «по всем, кроме самых непонятных сценариев», потому что даже при желании рекомбинировать элементы мне было бы тяжело иметь дело с несколькими пробелами. Я хотел бы каноническую форму - один пробел между каждым. Так что я с уважением не согласен - это будет «редко неправильно», а не «обычно неправильно».
— Майкл Соренс

1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
— Росс Прессер

3
Если вы действительно думаете, что это неясно, тогда, я думаю, нам придется согласиться не соглашаться, но если я оставлю эту функцию вне своего программного обеспечения, я потеряю свою работу. Пользователям нравится, что их контент выглядит так, как он хочет.
— Росс Прессер

4
Это должен быть принятый ответ, так как он гораздо более полный.
— Деннис

1
Мне интересно, почему вы добавили .Where(s => s != string.Empty)в Regex. Поскольку вы указываете \s+(любое количество пробелов), между ними не может быть пустых элементов.
— Джек Миллер

44

Согласно документации :

Если параметр разделителя имеет значение NULL или не содержит символов, символы пробела считаются разделителями. Пробельные символы определяются стандартом Unicode и возвращают true, если они передаются в метод Char.IsWhiteSpace.

Так что просто позвоните. myStr.Split();Нет необходимости передавать что-либо, потому что разделитель - это paramsмассив.


11

Почему вы не используете ?:

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

2
Нет перегрузки Split, которая занимает два символа.
— Такрл

1
@takrl: Посмотрите здесь открытую строку [] Split (params char [] separator) .NET v2
— Ренатас М.

Да, это занимает массив символов. Ваш фрагмент кода передает два отдельных символа.
— Такрл

15
@takrl: ты знаешь, что такое ключевое слово params ???
— Ренатас М.

Довольно круто, +1 за это. Вероятно, человек, который проголосовал, тоже не знал.
— Такрл

3

Обратите внимание, что соседние пробелы НЕ будут рассматриваться как один разделитель, даже при использовании String.Split(null). Если какие-либо из ваших токенов разделены несколькими пробелами или табуляциями, вы получите пустые строки, возвращенные в ваш массив.

Из документации:

Каждый элемент разделителя определяет отдельный символ разделителя. Если два разделителя являются смежными или в начале или конце этого экземпляра найден разделитель, соответствующий элемент массива содержит значение Empty.


2

Так что не копируйте и не вставляйте! Извлеките функцию для разделения и используйте ее снова.

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

Повторное использование кода ваш друг.



1

ты можешь использовать

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

разбить строку.


0

Разве вы не можете сделать это встроенным?

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

В противном случае, если вы будете делать именно это часто, вы всегда можете создать константу или что-то, содержащее этот массив символов.

Как отметили другие, вы можете в соответствии с документацией также использовать nullили пустой массив. Когда вы это сделаете, он будет автоматически использовать пробельные символы.

var sizes = subject.Split(null);

0

Если повторение того же кода является проблемой, напишите метод расширения в классе String, который инкапсулирует логику разделения.


1
Это на самом деле не отвечает на вопрос, извините.
— p.campbell

п. Кэмпбелл: Да, это так: OP запросил решение, которое не требует повсеместного копирования массива символов. Очевидное решение - создать функцию для выполнения задачи. Этот ответ указывает на то, что такая функция может быть методом расширения. (Ответ может быть улучшен, показывая код, чтобы сделать это ...)
— ToolmakerSteve

Используя наш сайт, вы подтверждаете, что прочитали и поняли нашу Политику в отношении файлов cookie и Политику конфиденциальности.
Licensed under cc by-sa 3.0 with attribution required.