2010-02-04 146 views
54

我需要从另一个字符串中删除第一个(也是唯一的第一个)字符串。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; 

这似乎是一个大量的代码。

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

回答

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

对于涉及非ASCII字符的字符串,此答案可能会中断。例如,在美国文化下,'æ'和'ae'被认为是平等的。尝试从'Encyclopædia'中删除'paedia'将会抛出一个'ArgumentOutOfRangeException',因为当匹配的子字符串只包含5时你试图删除6个字符。 – Douglas 2016-02-18 15:13:43

+1

我们可以这样修改它:'sourceString.IndexOf(removeString,StringComparison。 Ordinal)'以避免例外。 – 2016-12-20 19:37:57

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

编辑:@OregonGhost是正确的。我自己会用条件来打破剧本来检查这样的事件,但是我的操作是根据一些要求给出的字符串属于彼此。业务所需的异常处理规则可能有望实现这种可能性。我自己会使用一些额外的行来执行有条件的检查,并且对于那些可能没有花时间仔细阅读它的初级开发人员来说,它会使它更具可读性。

+6

这将崩溃,如果removeString不sourceString遏制。 – OregonGhost 2010-02-04 17:13:08

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(输入 “”,1);说要在输入中查找与该模式匹配的任何内容,用“”,1次。

+2

就像你解决了这个问题。当使用正则表达式来解决像这样的问题时,请考虑性能。 – Thomas 2012-10-16 15:32:55

6

您可以使用扩展方法来获得乐趣。通常我不建议将扩展方法附加到像字符串这样的通用类,但就像我说的这很有趣。我借鉴了卢克的回答,因为重新发明车轮毫无意义。

[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); 
    } 
} 
+0

为什么你通常不建议将扩展方法附加到像String这样的通用类?这有什么明显的缺点? – 2017-10-11 09:55:01

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

    } 
12
sourceString.Replace(removeString, ""); 
+7

[String.Replace](https://msdn.microsoft.com/en-us/library/fk49wtc1%28v=vs.110%29.aspx)说,它“* [r] eturns一个新的字符串,其中所有当前实例中指定字符串的出现被替换为另一个指定的字符串*“。 OP想要替换**第一次**事件。 – 2015-08-04 08:42:01

+2

另外,您应该解释一下您的答案,因为仅有代码的答案是不可接受的。看看其他答案,并将它们与你的一些提示进行比较。 – 2015-08-04 08:43:23

相关问题