Obter Substring - tudo antes de determinado caractere


124

Estou tentando descobrir a melhor maneira de obter tudo antes do caractere - em uma string. Alguns exemplos de strings estão abaixo. O comprimento da corda anterior - varia e pode ter qualquer comprimento

223232-1.jpg
443-2.jpg
34443553-5.jpg

então eu preciso do valor que é do índice inicial de 0 para a direita antes de -. Portanto, as substrings seriam 223232, 443 e 34443553

Respostas:


144

Exemplo de .Net Fiddle

class Program
{
    static void Main(string[] args)
    {
        Console.WriteLine("223232-1.jpg".GetUntilOrEmpty());
        Console.WriteLine("443-2.jpg".GetUntilOrEmpty());
        Console.WriteLine("34443553-5.jpg".GetUntilOrEmpty());

        Console.ReadKey();
    }
}

static class Helper
{
    public static string GetUntilOrEmpty(this string text, string stopAt = "-")
    {
        if (!String.IsNullOrWhiteSpace(text))
        {
            int charLocation = text.IndexOf(stopAt, StringComparison.Ordinal);

            if (charLocation > 0)
            {
                return text.Substring(0, charLocation);
            }
        }

        return String.Empty;
    }
}

Resultados:

223232
443
34443553
344

34

2
Por favor, faça um favor a eles e adicionar a verificação de erros, bem supondo que ele pretende fazer uma função fora deste :)
Josh

Obrigado, eu estava perto disso, mas estava curioso para saber se alguém tinha uma maneira diferente de fazer isso além desta combinação. Mas sim, isso funciona muito bem e ainda é muito curto.
PositiveGuy

14
Se você queria um one-liner sem perder adequada "não encontrado" verificando então você poderia fazer algo como isto:string result = source.Substring(0, Math.Max(source.IndexOf('-'), 0))
LukeH

2
Em vez de s.Substring(0, n)se pode usar s.Remove(n)quando se sabe (como aqui) que o comprimento da string sexcede estritamente n.
Jeppe Stig Nielsen

@LukeH Se IndexOf retornar -1 no seu exemplo, uma string vazia seria retornada, não seria?
esmagar

124

Use a função de divisão .

static void Main(string[] args)
{
    string s = "223232-1.jpg";
    Console.WriteLine(s.Split('-')[0]);
    s = "443-2.jpg";
    Console.WriteLine(s.Split('-')[0]);
    s = "34443553-5.jpg";
    Console.WriteLine(s.Split('-')[0]);

Console.ReadKey();
}

Se sua string não tiver um -, você receberá toda a string.


4
E se você tiver mais de um hífen, obterá vários elementos em sua matriz.
James Dunne

2
Na verdade, James, então isso seria apenas uma solução se você esperasse apenas um hífen. Suponho que você poderia usar métodos Linq como pular e agregar para obter o que queria, mas então você tem mais código do que os métodos que já foram propostos. Tudo depende de quanto você sabe sobre os dados recebidos.
Dominic Cronin

7
E, alguns anos depois, acabei de perceber que era rápido demais para admitir o argumento de James. A pergunta pergunta como encontrar a string antes de um determinado caractere. Instâncias adicionais desse personagem são, portanto, irrelevantes, e aceitar [0] "apenas funcionaria". Obviamente, ainda depende de quanto confiamos nos dados recebidos. E se não houver '-'?
Dominic Cronin

1
Acho que o argumento do @ JamesDunne foi que, ao se dividir em uma matriz, você cria um monte de seqüências desnecessárias - lixo desnecessário.
esmagar

1
Eu não me preocuparia com "lixo desnecessário". Quaisquer strings extras criadas dessa maneira seriam imediatamente inacessíveis e, portanto, coletadas na geração 0, o que é uma sobrecarga extremamente baixa. O design do coletor de lixo destina-se explicitamente a permitir que um grande número de itens de vida curta seja usado sem quase nenhuma despesa.
Dominic Cronin

65
String str = "223232-1.jpg"
int index = str.IndexOf('-');
if(index > 0) {
    return str.Substring(0, index)
}

upvote porque eu preciso saber o índice do separador
Piero Alberto

3
Esta é realmente a mesma resposta que Fredou deu (atualmente a resposta principal), exceto que omite o tratamento do caso em que nenhuma correspondência foi encontrada.
Dominic Cronin

7

As coisas mudaram um pouco desde o início desta discussão.

Agora você pode usar

string.Concat(s.TakeWhile((c) => c != '-'));

Como isso compara o desempenho com a combinação óbvia de IndexOf e Substring? Presumo que ele esteja anexando cada caractere a um StringBuilder e, em seguida, produzindo uma string no final. Há também algumas chamadas de função misturadas. Seria bom se Substring pudesse simplesmente aceitar -1 como um argumento "length" que significa "fim da string".
crush

1
É pior para a eficiência. Como você diz, ele usa um construtor de strings e, depois de inspecionar o código, chama ToString em cada caractere. É mais claro se você estiver procurando por mais de um caractere, pois poderá reescrever o lambda facilmente.
Anthony Wieser

4

Uma maneira de fazer isso é usar String.Substringjunto com String.IndexOf:

int index = str.IndexOf('-');
string sub;
if (index >= 0)
{
    sub = str.Substring(0, index);
}
else
{
    sub = ... // handle strings without the dash
}

Começando na posição 0, retorne todo o texto até, mas não incluindo, o traço.


se o índice <= 0, você deve retornar string.empty.
Sem reembolsos Sem retornos

5
@ NRR: se você diz. O OP sabe os requisitos de negócio, e não você ou eu
Michael Petrotta

0

Com base na resposta do BrainCore:

    int index = 0;   
    str = "223232-1.jpg";

    //Assuming we trust str isn't null 
    if (str.Contains('-') == "true")
    {
      int index = str.IndexOf('-');
    }

    if(index > 0) {
        return str.Substring(0, index);
    }
    else {
       return str;
    }

0

Você pode usar expressões regulares para esse fim, mas é bom evitar exceções extras quando a string de entrada não corresponder à expressão regular.

Primeiro, para evitar dores de cabeça extras ao escapar para o padrão regex - poderíamos simplesmente usar a função para esse fim:

String reStrEnding = Regex.Escape("-");

Eu sei que isso não faz nada - como "-" é o mesmo que Regex.Escape("=") == "=", mas fará diferença, por exemplo, se o personagem é @"\".

Então, precisamos corresponder do início da string ao final da string ou, alternativamente, se o final não for encontrado - não corresponda a nada. (String vazia)

Regex re = new Regex("^(.*?)" + reStrEnding);

Se o seu aplicativo for crítico em termos de desempenho - separe uma linha para o novo Regex, se não estiver - você poderá ter tudo em uma linha.

E, finalmente, combine com a sequência e extraia o padrão correspondente:

String matched = re.Match(str).Groups[1].ToString();

Depois disso, você pode escrever uma função separada, como foi feita em outra resposta, ou escrever uma função lambda embutida. Eu escrevi agora usando ambas as notações - função lambda inline (não permite parâmetro padrão) ou chamada de função separada.

using System;
using System.Text.RegularExpressions;

static class Helper
{
    public static string GetUntilOrEmpty(this string text, string stopAt = "-")
    {
        return new Regex("^(.*?)" + Regex.Escape(stopAt)).Match(text).Groups[1].Value;
    }
}

class Program
{
    static void Main(string[] args)
    {
        Regex re = new Regex("^(.*?)-");
        Func<String, String> untilSlash = (s) => { return re.Match(s).Groups[1].ToString(); };

        Console.WriteLine(untilSlash("223232-1.jpg"));
        Console.WriteLine(untilSlash("443-2.jpg"));
        Console.WriteLine(untilSlash("34443553-5.jpg"));
        Console.WriteLine(untilSlash("noEnding(will result in empty string)"));
        Console.WriteLine(untilSlash(""));
        // Throws exception: Console.WriteLine(untilSlash(null));

        Console.WriteLine("443-2.jpg".GetUntilOrEmpty());
    }
}

Btw - alterar o padrão regex para "^(.*?)(-|$)"permitirá pegar até o "-"padrão ou se o padrão não foi encontrado - pegar tudo até o final da string.


0

A maneira LINQy

String.Concat ("223232-1.jpg" .TakeWhile (c => c! = '-'))

(Mas você precisa testar se é nulo;)

Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.