【问题标题】:how to find all the double characters in a string in c#如何在c#中查找字符串中的所有双字符
【发布时间】:2016-02-08 05:20:59
【问题描述】:

我正在尝试使用 C# 计算字符串中所有 double 字符的数量,即 "ssss" 应该是两个双打而不是三个双打。

例如,现在我必须像这样在字符串中执行 for 循环

string s="shopkeeper";
for(int i=1;i<s.Length;i++) if(s[i]==s[i-1]) d++;

最后d的值应该是1

有没有更短的方法来做到这一点?在 linq 或正则表达式中?什么是性能影响,最有效的方法是什么?感谢您的帮助

我已阅读 [How to check repeated letters in a string c#] 和 这很有帮助,但不解决双字符,我正在寻找 双字符

【问题讨论】:

  • 我认为,这是最好的方法(简单快速)
  • @Backs 谢谢我注意到 for 循环比正则表达式更快,我现在需要一个 linq 版本来明确比较选择哪种方法
  • 你应该坚持你的解决方案。 Linq 不能比这更快。 Linq 不是巫术魔法,而是其底层的普通代码。
  • 好吧,你的 for 循环也给出了 5。ssss 是 3 对 s,而不是 2,小心:)
  • 这是您想要的调整:if (s[i] == s[i - 1]) { d++; i++; }

标签: c# regex linq


【解决方案1】:

尝试使用正则表达式提取任何双字符:"(.)\1"

UPD:简单示例:

foreach (var match in Regex.Matches("shhopkeeper", @"(.)\1"))
   Console.WriteLine(match);

【讨论】:

  • 它会找到第一个双字母,不是吗?
  • @Backs 在 C# 中,您可以提取所有出现的位置。不同的。
  • @Backs 用示例扩展了答案。
  • @DiligentKeyPresser,你的答案很完美,我只需要用这一行d+=System.Text.RegularExpressions.Regex.Matches(s,@"(.)\1").Count; 替换我的 for 循环,但我需要与这个的 linq 版本进行比较,然后我做一个性能比较提出最终解决方案。
  • @DiligentKeyPresser - 好答案。这可以很好地计算所需的实际值 - Regex.Matches(word, @"(.)\1").Cast&lt;Match&gt;().Select(m =&gt; m.Length / 2).Sum()
【解决方案2】:

这行得通:

var doubles =
    text
        .Skip(1)
        .Aggregate(
            text.Take(1).Select(x => x.ToString()).ToList(),
            (a, c) =>
            {
                if (a.Last().Last() == c)
                    a[a.Count - 1] += c.ToString();
                else
                    a.Add(c.ToString());
                return a;
            })
        .Select(x => x.Length / 2)
        .Sum();

我给了我这些结果:

"shopkeeper" -> 1
"beekeeper" -> 2
"bookkeeper" -> 3
"boookkkeeeper" -> 3
"booookkkkeeeeper" -> 6

【讨论】:

    【解决方案3】:

    首先我想提一下,对于这个问题没有“自然”的 LINQ 解决方案,因此与简单的for 循环相比,每个标准的基于 LINQ 的解决方案都将是丑陋且效率极低的。

    但是,对于这个和类似的问题,有一个 LINQ“精神”解决方案,比如链接的 How to check repeated letters in a string c# 或者如果你想找到不 doubles,但可以说 triples, quadruples 等等。

    常见的子问题是,给定一些元素序列,为具有相同值的连续元素生成(value, count) 对组的新序列。

    可以使用这样的自定义扩展方法来完成(方法的名称可能不同,这不是重点):

    public static class EnumerableEx
    {
        public static IEnumerable<TResult> Zip<TSource, TResult>(this IEnumerable<TSource> source, Func<TSource, int, TResult> resultSelector, IEqualityComparer<TSource> comparer = null)
        {
            if (comparer == null) comparer = EqualityComparer<TSource>.Default;
            using (var e = source.GetEnumerator())
            {
                for (bool more = e.MoveNext(); more;)
                {
                    var value = e.Current;
                    int count = 1;
                    while ((more = e.MoveNext()) && comparer.Equals(e.Current, value)) count++;
                    yield return resultSelector(value, count);
                }
            }
        }
    }
    

    将此功能与标准LINQ结合使用,可以轻松解决原来的问题:

    var s = "shhopkeeperssss";
    var countDoubles = s.Zip((value, count) => count / 2).Sum();
    

    还有

    var countTriples = s.Zip((value, count) => count / 3).Sum();
    

    var countQuadruples = s.Zip((value, count) => count / 4).Sum();
    

    或链接中的问题

    var repeatedChars = s.Zip((value, count) => new { Char = value, Count = count })
        .Where(e => e.Count > 1);
    

    等等

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-01-07
      • 1970-01-01
      • 1970-01-01
      • 2021-08-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多