【问题标题】:How to split a string every time the character changes?每次字符更改时如何拆分字符串?
【发布时间】:2017-09-25 21:53:25
【问题描述】:

我想将abbbbcc 之类的字符串转换成这样的数组:C# 中的[a,bbbb,cc]。我已经尝试过来自this Java question 的正则表达式,如下所示:

var test = "aabbbbcc";
var split = new Regex("(?<=(.))(?!\\1)").Split(test);

但这导致我的序列[a,a,bbbb,b,cc,c]。如何在 C# 中实现相同的结果?

【问题讨论】:

  • 显示你的尝试...
  • @RufusL 我有。
  • 不,您说您尝试了其他帖子的答案,但您没有发布您正在尝试的实际代码(在 C# 中),因此我们可以帮助修复它。
  • 我没有投票结束,也没有否决这个问题。我只要求查看您正在尝试的代码,以便我可以帮助解决问题。查看How to create a Minimal, Complete, and Verifiable example 的帮助。
  • @RufusL 我已经在 StackOverflow 上发布了许多问题,并且通常总是包含我的代码 - 如果我认为它有用并且可以帮助那些试图帮助我的人。然而,在这种情况下,我认为没有人需要看到明确编写的 Regex().Split() 才能知道我是如何得到我显示的输出的。

标签: c#


【解决方案1】:

使用 Linq 可以轻松做到这一点,但我认为它的运行时不如正则表达式。

不过阅读起来要容易得多。

        var myString = "aaabbccccdeee";
        var splits = myString.ToCharArray()
             .GroupBy(chr => chr)
             .Select(grp => new string(grp.Key, grp.Count()));

返回值 `['aaa', 'bb', 'cccc', 'd', 'eee']

但是,如果您有像 "aabbaa" 这样的字符串,这将不起作用,您只会得到 ["aaaa","bb"] 而不是 ["aa","bb","aa"]

【讨论】:

  • 就我个人而言,要求它可以处理aabbaa
【解决方案2】:

这是一个使用Aggregate的LINQ解决方案:

var input = "aabbaaabbcc"; 
var result = input
    .Aggregate(" ", (seed, next) => seed + (seed.Last() == next ? "" : " ") + next)
    .Trim()
    .Split(' ');

它根据最后一个读取的字符聚合每个字符,然后如果遇到新字符,它会在累积的字符串中附加一个空格。然后,我在最后使用普通的String.Split 将其全部拆分。

结果:

[“aa”、“bb”、“aaa”、“bb”、“cc”]

【讨论】:

    【解决方案3】:

    这里有几件事会产生您所看到的输出:

    1. 正则表达式结合了正向向后查找和负向向前查找,以查找与它前面的字符匹配但与后面的字符不匹配的最后一个字符。

    2. 它为每个匹配创建捕获组,然后将其作为分隔符输入Split 方法。捕获组是负前瞻所必需的,具体是\1标识符,基本意思是“语句中第一个捕获组的值”,所以不能省略。

    3. Regex.Split,在识别拆分分隔符时给定一个或多个要匹配的捕获组,将包括用于每个单独拆分操作的分隔符。

    数字 3 是您的字符串数组看起来很奇怪的原因,Split 将在字符串中的最后一个 a 处拆分,变为 split[0]。其后是 split[1] 处的分隔符等...

    在调用 Split 时无法覆盖此行为。 根据 Gusman 的回答进行补偿,或者根据 Ruard 的回答预测 Matches 电话的结果,都会得到你想要的。

    【讨论】:

      【解决方案4】:

      我不知道如何通过拆分来完成它。但这可能是一个不错的选择:

      //using System.Linq;
      
      var test = "aabbbbcc";
      var matches = Regex.Matches(test, "(.)\\1*");
      var split = matches.Cast<Match>().Select(match => match.Value).ToList();
      

      【讨论】:

        【解决方案5】:

        说实话,我并不完全了解该正则表达式的工作原理,但您可以非常轻松地“修复”输出:

        Regex reg = new Regex("(?<=(.))(?!\\1)", RegexOptions.Singleline);
        var res = reg.Split("aaabbcddeee").Where((value, index) => index % 2 == 0 && value != "").ToArray();
        

        【讨论】:

        • 这是一个聪明的解决方法,如果一切都失败了,我可能会使用它,但如果有人可以解释正则表达式或提供非正则表达式解决方案,我更愿意。
        猜你喜欢
        • 1970-01-01
        • 2016-03-15
        • 2016-04-14
        • 2020-08-11
        • 2022-11-16
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多