C# - 从另一个字符串中删除第一次出现的子字符串的最简单方法

时间:2010-02-04 17:04:25

标签: c# string

我需要从另一个字符串中删除第一个(并且只是第一个)字符串。

以下是替换字符串"\\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;

这似乎是很多代码。

所以我的问题是:是否有更清晰/更可读/更简洁的方法来做到这一点?

7 个答案:

答案 0 :(得分:125)

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

答案 1 :(得分:24)

string myString = sourceString.Remove(sourceString.IndexOf(removeString),removeString.Length);
编辑:@OregonGhost是对的。我自己会用条件来破坏脚本来检查这种情况,但是我假设字符串被某些要求赋予了彼此属性。预计业务所需的异常处理规则可能会捕获这种可能性。我本人会使用一些额外的行来执行条件检查,并且对于那些可能没有花时间仔细阅读它的初级开发人员来说,它会更具可读性。

答案 2 :(得分:14)

sourceString.Replace(removeString, "");

答案 3 :(得分:10)

为此编写快速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次。

答案 4 :(得分:6)

您可以使用扩展方法来获得乐趣。通常我不建议将扩展方法附加到像字符串这样的通用类,但就像我说这很有趣。我借用了@ 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);
    }
}

答案 5 :(得分:2)

我绝对同意这对于扩展方法是完美的,但我认为它可以稍微改进一下。

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

    }

答案 6 :(得分:0)

如果您想使用一种简单的方法来解决此问题。 (可用作扩展名)

请参见下文:

    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的答案,并对其进行了修改。

别忘了StringComparison.Ordinal来防止区域性设置出现问题。 https://www.jetbrains.com/help/resharper/2018.2/StringIndexOfIsCultureSpecific.1.html