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