Get Substring-특정 문자 이전의 모든 것


124

문자열에서-문자 앞에 모든 것을 가져 오는 가장 좋은 방법을 찾으려고합니다. 다음은 몇 가지 예제 문자열입니다. 이전 문자열의 길이-다양하며 모든 길이 가능

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

그래서 0의 시작 인덱스에서-바로 앞의 값이 필요합니다. 따라서 부분 문자열은 223232, 443 및 34443553이됩니다.

답변:


144

.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;
    }
}

결과 :

223232
443
34443553
344

34

2
그들에게 호의를 베풀고 오류 검사를 추가하고 그가 이것으로 함수를 만들 계획이라고 가정합니다 :)
Josh

고맙지 만이 콤보가 아닌 다른 방법이 있는지 궁금했습니다. 그러나 네 이것은 훌륭하게 작동하며 여전히 꽤 짧습니다.
PositiveGuy

14
적절한 "찾을 수 없음"확인을 잃지 않고 한 줄짜리를 원한다면 다음과 같이 할 수 있습니다.string result = source.Substring(0, Math.Max(source.IndexOf('-'), 0))
LukeH

2
대신 s.Substring(0, n)하나를 사용할 수 있습니다 s.Remove(n)문자열의 길이가 있음 (여기처럼)이라고 할 때 s엄격하게 초과 n.
Jeppe Stig Nielsen

@LukeH IndexOf가 예제에서 -1을 반환하면 빈 문자열이 반환됩니다. 그렇지 않습니까?
crush

124

분할 기능을 사용하십시오 .

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();
}

문자열에 a가 없으면 -전체 문자열을 얻습니다.


4
하이픈이 두 개 이상이면 배열에 여러 요소가 있습니다.
James Dunne

2
사실, James, 그래서 이것은 당신이 단 하나의 하이픈만을 기대하는 경우에만 해결책이 될 것입니다. 나는 당신이 원하는 것을 얻기 위해 skip 및 aggregate와 같은 Linq 방법을 사용할 수 있다고 가정하지만 이미 제안 된 방법보다 더 많은 코드를 가지고 있습니다. 그것은 모두 들어오는 데이터에 대해 얼마나 알고 있는지에 달려 있습니다.
Dominic Cronin

7
그리고 몇 년 후, 나는 제임스의 주장을 인정하기에는 너무 빠르다는 것을 깨달았습니다. 질문은 특정 문자 앞의 문자열을 찾는 방법을 묻습니다. 따라서 해당 캐릭터의 추가 인스턴스는 무관하며 [0]을 사용하면 "그냥 작동"됩니다. 물론 들어오는 데이터를 얼마나 신뢰하는지에 따라 달라집니다. '-'가 전혀 없다면?
Dominic Cronin 2015 년

1
@JamesDunne의 요점은 배열로 분할함으로써 불필요한 문자열 인 불필요한 쓰레기를 생성한다는 것입니다.
crush

1
나는 "불필요한 쓰레기"에 대해 걱정하지 않을 것입니다. 이러한 방식으로 생성 된 추가 문자열은 즉시 도달 할 수 없으므로 0 세대에서 수집되며 이는 실제로 매우 낮은 오버 헤드입니다. 가비지 수집기 디자인은 많은 수의 단기 항목을 거의 비용없이 사용할 수 있도록 명시 적으로 설계되었습니다.
Dominic Cronin 2015 년

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

내가 구분자의 색인을 알아야하기 때문에 upvote
Piero Alberto

3
이것은 실제로 Fredou가 준 (현재 최고 답변)과 동일한 답변입니다. 단, 일치하는 항목이없는 경우 처리를 생략합니다.
Dominic Cronin 2016 년

7

이 스레드가 시작된 이후로 상황이 조금씩 움직였습니다.

이제 사용할 수 있습니다.

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

성능면에서 명백한 IndexOf 및 Substring 조합과 어떻게 비교됩니까? 각 문자를 StringBuilder에 추가 한 다음 끝에 문자열을 생성한다고 가정합니다. 또한 몇 가지 함수 호출이 혼합되어 있습니다. Substring이 "문자열의 끝"을 의미하는 "길이"인수로 -1을 취할 수 있다면 좋았을 것입니다.
crush

1
효율성 측면에서 더 나쁩니다. 당신이 말했듯이, 그것은 문자열 작성기를 사용하고 코드를 검사하면 각 문자에서 ToString을 호출하는 것처럼 보입니다. 람다를 쉽게 다시 작성할 수 있으므로 두 개 이상의 문자를 찾는 것이 더 명확합니다.
Anthony Wieser 2015 년

5

이를 수행하는 한 가지 방법은 다음 String.Substring과 함께 사용하는 것입니다 String.IndexOf.

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

위치 0에서 시작하여 대시를 제외한 모든 텍스트를 반환합니다.


index <= 0이면 string.empty를 반환해야합니다.
환불 없음 반환

5
@NRNR : 그렇게 말하면. OP는
귀 하나 나가

0

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

이 목적으로 정규식을 사용할 수 있지만 입력 문자열이 정규식과 일치하지 않을 때 추가 예외를 피하는 것이 좋습니다.

먼저 정규식 패턴으로 이스케이프하는 추가 골칫거리를 피하기 위해-우리는 그 목적으로 함수를 사용할 수 있습니다.

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

나는 이것이 아무 일도하지 않는다는 것을 알고있다. "-"는와 같지만 Regex.Escape("=") == "=", 예를 들어 character가이면 차이를 만들 것이다 @"\".

그런 다음 문자열 구걸에서 문자열 끝까지 일치시켜야합니다. 또는 끝이 없으면 아무 것도 일치하지 않습니다. (빈 문자열)

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

응용 프로그램이 성능에 중요한 경우-새 Regex에 대한 별도의 줄이 아니라면 모든 것을 한 줄에 가질 수 있습니다.

마지막으로 문자열과 일치하고 일치하는 패턴을 추출합니다.

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

그 후에 다른 답변에서했던 것처럼 별도의 함수를 작성하거나 인라인 람다 함수를 작성할 수 있습니다. 이제 인라인 람다 함수 (기본 매개 변수를 허용하지 않음) 또는 별도의 함수 호출과 같은 두 가지 표기법을 사용하여 작성했습니다.

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-정규식 패턴을 변경 하면 패턴이 "^(.*?)(-|$)"나타날 때까지 "-"또는 패턴을 찾을 수없는 경우 문자열 끝까지 모든 것을 선택할 수 있습니다.


0

LINQy 방식

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

(그러나 null을 테스트해야합니다.)

당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.