Melhor maneira de especificar espaço em branco em uma operação String.Split

243

Estou dividindo uma seqüência de caracteres com espaço em branco da seguinte maneira:

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

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

É cansativo definir a matriz char [] em todo lugar no meu código que eu quero fazer isso. Existe uma maneira mais eficaz que não exija a criação da matriz de caracteres (que é propensa a erros se copiada em lugares diferentes)?

John Saunders
fonte
1
faz isso: myStr.Split (''); não funciona?
22811 Woolagaroo
4
Se eu entendi corretamente isso só vai procurar um espaço, não genérico espaço em branco
Veja também possível duplicado, mas essas respostas posteriores têm SplitStringOptions. stackoverflow.com/questions/1562981/…
goodeye

Respostas:

469

Se você acabou de ligar:

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

ou:

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

o espaço em branco é assumido como o caractere de divisão. Na string.Split(char[])página de documentação do método .

Se o parâmetro separador for nullou não contiver caracteres, os caracteres de espaço em branco serão assumidos como delimitadores. Caracteres de espaço em branco são definidos pelo padrão Unicode e retornam truese forem passados ​​para o Char.IsWhiteSpacemétodo.

Sempre, sempre, sempre leia a documentação!

Jason
fonte
2
O problema com a divisão por espaço em branco é que, se você precisar reuni-lo novamente, não sabe qual caractere de espaço em branco deve ser colocado de volta.
Ross Presser
19
(char[])nullé um pouco melhor, pois evita a criação de um novo objeto. (Você não pode usar nullcom nenhuma optionssobrecarga).
Artfunkel 07/07
5
@ RossPresser: Reunir novamente uma string é um problema completamente diferente, então eu não diria que isso é um problema aqui. Mas se tudo o que você precisa fazer é juntar as cordas exatamente como antes, talvez seja melhor manter o original.
stakx - não está mais contribuindo com
4
Pergunta estúpida, mas se você usar null, ainda precisa especificar StringSplitOption.RemoveEmptyEntriesou eles são ignorados por padrão?
yu_ominae 11/11
2
@RossPresser: Como o String.Split não fornece nenhum mecanismo para rastrear os caracteres usados ​​para dividir a string, sua observação não é relevante: não é possível alcançar o que você procura usando o String.Split, o que exige uma sessão de perguntas e respostas diferente.
Página
207

Sim, é necessário mais uma resposta aqui!

Todas as soluções até agora abordam o domínio bastante limitado da entrada canônica , a saber: um único caractere de espaço em branco entre os elementos (embora seja comum o @cherno pelo menos mencionar o problema). Mas eu afirmo que em todos os cenários, exceto os mais obscuros, a divisão de todos eles deve produzir resultados idênticos:

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(em qualquer um dos sabores mostrados nas outras respostas aqui) simplesmente não funciona bem, a menos que você associe a RemoveEmptyEntriesopção a um destes:

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

Como mostra a ilustração, a omissão da opção gera quatro resultados diferentes (rotulados como A, B, C e D) vs. o resultado único de todas as quatro entradas quando você usa RemoveEmptyEntries:

String.Split vs Regex.Split

Obviamente, se você não gosta de usar opções, basta usar a alternativa regex :-)

Regex.Split(myStr, @"\s+").Where(s => s != string.Empty)
Michael Sorens
fonte
4
@RossPresser, acho que isso é coberto pelo meu qualificador "em todos os cenários, exceto os mais obscuros", porque mesmo ao recombinar os elementos, seria difícil ter um caso em que me preocupo com vários espaços. Eu gostaria de uma forma canônica - um espaço entre cada um. Por isso, discordo respeitosamente - seria "raramente errado" e não "geralmente errado".
precisa saber é o seguinte
1
CapitalizeEveryWord("This is line one.\n \nThis is line three.")
Ross Presser
3
Se você realmente acha que isso é obscuro, acho que teremos que concordar em discordar, mas se eu deixasse essa função fora do meu software, perderia o emprego. Os usuários gostam de seu conteúdo com a aparência que desejam.
Ross Presser
4
Esta deve ser uma resposta aceita, pois é muito mais completa.
217 Dennis
1
Gostaria de saber por que você adicionou .Where(s => s != string.Empty)ao Regex. Como você especifica \s+(qualquer número de espaços), não pode haver nenhum item vazio no meio.
Jack Miller
44

De acordo com a documentação :

Se o parâmetro separador for nulo ou não contiver caracteres, os caracteres de espaço em branco serão assumidos como delimitadores. Caracteres de espaço em branco são definidos pelo padrão Unicode e retornam true se forem passados ​​para o método Char.IsWhiteSpace.

Então basta ligar myStr.Split();Não há necessidade de passar nada, porque o separador é uma paramsmatriz.

ageektrapped
fonte
11

Por que você não usa ?:

string[] ssizes = myStr.Split(' ', '\t');
Renatas M.
fonte
2
Não há sobrecarga de divisão que leva dois caracteres.
23411 taktl
1
@takrl: Olhe aqui public string [] Split (params char [] separador) .NET v2
Renatas M.
Sim, isso requer uma matriz de caracteres. Seu snippet de código passa dois caracteres únicos.
takrl 24/05
15
@takrl: você sabe qual é a palavra-chave params ???
Renatas M. 24/11
Muito legal, +1 por isso. Provavelmente a pessoa que votou mal também não sabia.
takrl 24/05
3

Observe que o espaço em branco adjacente NÃO será tratado como um único delimitador, mesmo quando usado String.Split(null). Se algum de seus tokens for separado por vários espaços ou guias, você receberá as seqüências de caracteres vazias em sua matriz.

A partir da documentação:

Cada elemento do separador define um caracter delimitador separado. Se dois delimitadores forem adjacentes ou um delimitador for encontrado no início ou no final desta instância, o elemento da matriz correspondente conterá Vazio.

cherno
fonte
2

Portanto, não copie e cole! Extraia uma função para fazer sua divisão e reutilize-a.

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

A reutilização de código é seu amigo.

Tim Rogers
fonte
1

você pode usar

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

para dividir a string.

Haxer
fonte
0

Você não pode fazê-lo em linha?

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

Caso contrário, se você fizer exatamente exatamente isso, poderá sempre criar constante ou algo que contenha essa matriz de caracteres.

Como outros observaram, de acordo com a documentação, você também pode usar nullou uma matriz vazia. Ao fazer isso, ele usará caracteres de espaço em branco automaticamente.

var sizes = subject.Split(null);
Svish
fonte
0

Se repetir o mesmo código, escreva um método de extensão na classe String que encapsule a lógica de divisão.

Xhalent
fonte
1
Isso realmente não responde à pergunta, desculpe.
precisa saber é
p. campbell: Sim, sim: O OP pediu uma solução que não requer a cópia da matriz de caracteres em todos os lugares. Uma solução óbvia é criar uma função para executar a tarefa. Esta resposta indica que essa função pode ser um método de extensão. (A resposta poderia ser melhorado, mostrando o código para fazê-lo ...)
ToolmakerSteve