[c#] 다른 문자열에서 첫 번째 부분 문자열을 제거하는 가장 간단한 방법

다른 문자열에서 문자열의 첫 번째 (그리고 첫 번째 만) 발생을 제거해야합니다.

다음은 문자열을 대체하는 예 "\\Iteration"입니다. 이:

ProjectName \\ Iteration \\ Release1 \\ Iteration1

다음과 같이 될 것입니다.

ProjectName \\ Release1 \\ Iteration1

이 작업을 수행하는 코드는 다음과 같습니다.

const string removeString = "\\Iteration";
int index = sourceString.IndexOf(removeString);
int length = removeString.Length;
String startOfString = sourceString.Substring(0, index);
String endOfString = sourceString.Substring(index + length);
String cleanPath = startOfString + endOfString;

그것은 많은 코드처럼 보입니다.

그래서 내 질문은 이것입니다 : 이것을 수행하는 더 깨끗하고 / 더 읽기 쉽고, 더 간결한 방법이 있습니까?



답변

int index = sourceString.IndexOf(removeString);
string cleanPath = (index < 0)
    ? sourceString
    : sourceString.Remove(index, removeString.Length);


답변

string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);

편집 : @OregonGhost가 맞습니다. 나는 그러한 발생을 확인하기 위해 조건부로 스크립트를 분해 할 것이지만, 어떤 요구 사항에 의해 문자열이 서로에게 속하도록 주어진다는 가정하에 작업하고있었습니다. 비즈니스에 필요한 예외 처리 규칙이 이러한 가능성을 포착 할 것으로 예상 될 수 있습니다. 필자는 몇 줄을 추가로 사용하여 조건부 검사를 수행하고 시간을 들여 충분히 읽지 못하는 주니어 개발자에게 좀 더 읽기 쉽게 만들었습니다.


답변

sourceString.Replace(removeString, "");


답변

이에 대한 빠른 TDD 테스트를 작성했습니다.

    [TestMethod]
    public void Test()
    {
        var input = @"ProjectName\Iteration\Release1\Iteration1";
        var pattern = @"\\Iteration";

        var rgx = new Regex(pattern);
        var result = rgx.Replace(input, "", 1);

        Assert.IsTrue(result.Equals(@"ProjectName\Release1\Iteration1"));
    }

rgx.Replace (input, “”, 1); 입력에서 패턴과 일치하는 항목을 검색하라고 “”, 1 번.


답변

재미를 위해 확장 방법 을 사용할 수 있습니다 . 일반적으로 문자열과 같은 범용 클래스에 확장 메서드를 연결하지 않는 것이 좋지만 이것이 재미 있다고 말했듯이. 바퀴를 재발 명 할 필요가 없기 때문에 @Luke의 대답을 빌 렸습니다.

[Test]
public void Should_remove_first_occurrance_of_string() {

    var source = "ProjectName\\Iteration\\Release1\\Iteration1";

    Assert.That(
        source.RemoveFirst("\\Iteration"),
        Is.EqualTo("ProjectName\\Release1\\Iteration1"));
}

public static class StringExtensions {
    public static string RemoveFirst(this string source, string remove) {
        int index = source.IndexOf(remove);
        return (index < 0)
            ? source
            : source.Remove(index, remove.Length);
    }
}


답변

이 문제를 해결하는 간단한 방법을 원할 경우. (확장자로 사용 가능)

아래를 참조하십시오.

    public static string RemoveFirstInstanceOfString(this string value, string removeString)
    {
        int index = value.IndexOf(removeString, StringComparison.Ordinal);
        return index < 0 ? value : value.Remove(index, removeString.Length);
    }

용법:

    string valueWithPipes = "| 1 | 2 | 3";
    string valueWithoutFirstpipe = valueWithPipes.RemoveFirstInstanceOfString("|");
    //Output, valueWithoutFirstpipe = " 1 | 2 | 3";

@LukeH 및 @Mike의 답변에서 영감을 얻고 수정했습니다.

Culture 설정 문제를 방지하려면 StringComparison.Ordinal을 잊지 마세요.
https://www.jetbrains.com/help/resharper/2018.2/StringIndexOfIsCultureSpecific.1.html


답변

나는 이것이 확장 방법에 완벽하다는 데 확실히 동의하지만 조금 개선 될 수 있다고 생각합니다.

public static string Remove(this string source, string remove,  int firstN)
    {
        if(firstN <= 0 || string.IsNullOrEmpty(source) || string.IsNullOrEmpty(remove))
        {
            return source;
        }
        int index = source.IndexOf(remove);
        return index < 0 ? source : source.Remove(index, remove.Length).Remove(remove, --firstN);
    }

이것은 항상 재미있는 약간의 재귀를 수행합니다.

다음은 간단한 단위 테스트입니다.

   [TestMethod()]
    public void RemoveTwiceTest()
    {
        string source = "look up look up look it up";
        string remove = "look";
        int firstN = 2;
        string expected = " up  up look it up";
        string actual;
        actual = source.Remove(remove, firstN);
        Assert.AreEqual(expected, actual);

    }