【问题标题】:How to remove all but the first occurences of a character from a string?如何从字符串中删除除第一次出现的字符之外的所有字符?
【发布时间】:2016-04-08 14:27:25
【问题描述】:

我有一个文本字符串,并希望确保它最多包含一次特定字符 (,)。因此,我想保留第一个,但只需删除该字符的所有进一步出现。

我怎样才能使用 C# 以最优雅的方式做到这一点?

【问题讨论】:

    标签: c# string replace


    【解决方案1】:

    这可行,但肯定不是最优雅的:-)

    string a = "12,34,56,789";
    int pos = 1 + a.IndexOf(',');
    return a.Substring(0, pos) + a.Substring(pos).Replace(",", string.Empty);
    

    【讨论】:

    • 我觉得它很优雅 ;) 如果你想保留 2 个字符 f.e.,它只有一个缺点
    • @TimSchmelter “保留 2 个字符”是什么意思?
    • @silkfire:好吧,尝试指定您不想删除除第一个之外的所有内容,而是删除除前 2 个之外的所有内容
    • 我明白你现在的意思了。为此,您可以将 a.IndexOf 替换为返回第 N 次出现的子字符串的方法:stackoverflow.com/questions/186653/…
    【解决方案2】:

    您可以使用计数器变量和StringBuilder 来有效地创建新字符串:

    var sb = new StringBuilder(text.Length);
    int maxCount = 1;
    int currentCount = 0;
    char specialChar = ',';
    foreach(char c in text)
        if(c != specialChar || ++currentCount <= maxCount)
            sb.Append(c);
    text = sb.ToString();
    

    这种方法不是最短的,但它很有效,您可以指定要保留的字符数。

    这是使用 LINQ 的更“优雅”的方式:

    int commasFound = 0; int maxCommas = 1;
    text = new string(text.Where(c => c != ',' || ++commasFound <= maxCommas).ToArray());
    

    我不喜欢它,因为它需要修改查询中的变量,所以会产生副作用。

    【讨论】:

    • 我认为 LINQ 非常优雅 :)
    • @Rawling:编辑了我的答案以评论我为什么不喜欢它(即使我喜欢 LINQ)。
    • 我真的很喜欢你的 LINQ 语句,但我还不明白你提到的副作用。您希望那里发生什么?
    • 在这种情况下,它可以正常工作。但是在 linq 查询中局部变量的使用和初始化是一个炸弹,在更复杂的情况或查询下可能会爆炸。此变量只有一种状态,但可以通过多种方式执行查询,例如,如果您包含 OrderBy。因此,最佳实践是使用封装变量的此类任务的方法。
    【解决方案3】:

    正则表达式很优雅,对吧?

    Regex.Replace("Eats, shoots, and leaves.", @"(?<=,.*),", "");
    

    这将替换每个逗号,只要它前面有一个逗号,什么都没有。

    (其实可能不太优雅——可能只有一行代码,但也可能是O(n^2)...)

    【讨论】:

    • 当我将它放入测试仪时它不起作用。向后看中的量词使其宽度不固定
    • @user1040975 您可能使用了不同风格的正则表达式。
    【解决方案4】:

    如果您不处理大字符串并且您非常喜欢 Linq oneliners:

    public static string KeepFirstOccurence (this string @string, char @char)
    {
        var index = @string.IndexOf(@char);
        return String.Concat(String.Concat(@string.TakeWhile(x => @string.IndexOf(x) < index + 1)), String.Concat(@string.SkipWhile(x=>@string.IndexOf(x) < index)).Replace(@char.ToString(), ""));
    }
    

    【讨论】:

      【解决方案5】:

      您可以编写一个类似以下的函数,根据您正在搜索的内容的位置(通过String.Split() 方法)将字符串分成两部分,并且它只会从第二部分中删除匹配项(使用String.Replace()) :

      public static string RemoveAllButFirst(string s, string stuffToRemove)
      {
          // Check if the stuff to replace exists and if not, return the original string
          var locationOfStuff = s.IndexOf(stuffToRemove);
          if (locationOfStuff < 0)
          {
              return s;
          }
          // Calculate where to pull the first string from and then replace the rest of the string
          var splitLocation = locationOfStuff + stuffToRemove.Length;
          return s.Substring(0, splitLocation) +  (s.Substring(splitLocation)).Replace(stuffToRemove,"");
      }
      

      你可以简单地调用它:

      var output = RemoveAllButFirst(input,",");
      

      更漂亮的方法实际上可能涉及构建一个更干净地处理此问题的扩展方法:

      public static class StringExtensions
      {
           public static string RemoveAllButFirst(this string s, string stuffToRemove)
           {
                 // Check if the stuff to replace exists and if not, return the 
                 // original string
                 var locationOfStuff = s.IndexOf(stuffToRemove);
                 if (locationOfStuff < 0)
                 {
                     return s;
                 }
                 // Calculate where to pull the first string from and then replace the rest of the string
                 var splitLocation = locationOfStuff + stuffToRemove.Length;
                 return s.Substring(0, splitLocation) +  (s.Substring(splitLocation)).Replace(stuffToRemove,"");
           }
      }
      

      将通过以下方式调用:

      var output = input.RemoveAllButFirst(",");
      

      你可以see a working example of it here

      【讨论】:

      • StringExtensions 需要是静态类,第一个参数需要是this string s
      • 由于某种原因,我的回复似乎是在我没有注意到的情况下提交的。我已经相应地更新了函数。感谢您的提醒。
      【解决方案6】:
          static string KeepFirstOccurance(this string str, char c)
          {
              int charposition = str.IndexOf(c);
              return str.Substring(0, charposition + 1) +
                         str.Substring(charposition, str.Length - charposition)
                         .Replace(c, ' ').Trim();
          }
      

      【讨论】:

        【解决方案7】:

        Linq 很短;将字符串拆分为字符,保持不同的集合并连接回字符串。

        text = string.Join("", text.Select(c => c).Distinct());
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2018-07-08
          • 1970-01-01
          • 2011-06-23
          • 2013-12-15
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多