【问题标题】:How can I retrieve the count of a certain character in a string array?如何检索字符串数组中某个字符的计数?
【发布时间】:2020-06-21 22:57:12
【问题描述】:

我有这段代码来尝试计算在字符串数组中出现了多少传入的字符:

string[] doc1StrArray;
. . .
private int GetCountOfSpecificCharacter(string CharToCount)
{
    int count = 0;
    count = doc1StrArray.Count(f => f == CharToCount);
    return count;
}

...这样称呼:

iCountOfCommasInDoc1 = GetCountOfSpecificCharacter(",");

...但它不起作用。它找不到逗号,例如,在以下情况下,尽管文档确实包含逗号。

更新

两者都有效 - Roman 的建议和 Teroneko 的建议:

private int GetCountOfSpecificCharacterInDoc1(char CharToCount)
{
    return doc1StrArray.Sum(s => s.Count(c => c == CharToCount));
}

private int GetCountOfSpecificCharacterInDoc2(char CharToCount)
{
    return doc2StrArray.SelectMany(x => x).Count(c => c == CharToCount);
}

...但我不知道哪个更好/更有效。

【问题讨论】:

  • 如果我没记错的话,您正在将字符串与字符进行比较。您需要检查数组中每个字符串中的每个字符
  • 也许还有:return string.Join("", doc1StrArray).Aggregate(0, (i, c) => c.Equals(CharToCount) ? ++i : i);

标签: c# arrays linq


【解决方案1】:
private int GetCountOfSpecificCharacter(char charToCount)
{
    int count = 0;
    foreach (var word in doc1StrArray)
        foreach (char character in word)
           if (character == charToCount)
               count++;
    return count;
}

【讨论】:

  • 所有答案中最有效的方法
【解决方案2】:

这是一个示例,您可以使用它来迭代字符串数组以检查字符在字符串中出现的次数,然后将其全部加起来。

string[] test = new string[] { 
    "This is, the first test string", 
    "This, is the second, test string", 
    "this is the, third"};

string inp = ",";
Console.WriteLine(test.Sum(stringItem => stringItem.Count(charItem => charItem.ToString().Equals(inp))));

// Prints 4

在比较期间,您可以将被迭代的字符转换为字符串以进行正确的string.Equals(string) 比较。您要将其转换为字符串的原因是字符“a”不等于字符串“a”。如果要进行字符比较,请参见下面的字符比较方法(但注意字符应与字符进行比较,字符串与字符串进行比较。)。

这可以是你的计数方法,

private int GetCountOfSpecificCharacter(string CharToCount)
{
    return doc1StrArray.Sum(stringItem => stringItem.Count(charItem => charItem.ToString().Equals(CharToCount)));
}

// And this one to use for Character Comparisons using `.ToCharArray()` method. 
// You can parse each character as well by the use of char.Parse(str)
private int GetCountOfSpecificCharacter(string CharToCount)
{
    return test.Sum(stringItem => stringItem.ToCharArray().Count(charItem => charItem.Equals(CharToCount.ToCharArray().First())));
}

【讨论】:

    【解决方案3】:

    @Jawad 是对的。你可以这样做来实现你的目标:

    var count = doc1StrArray.SelectMany(x => x).Count(c => c == CharToCount);
    

    这会选择每个数组项中的任何字符并将它们作为一个IEnumerable<char> 返回。当您知道在其上应用.Count(..) 时,您就在计算每个字符。

    编辑: 我做了一些测试,似乎for循环是最快的

            public int GetAmountOfChar(string[] strings, char character) {
                int amountOfChar = 0;
                var linesLength = strings.Length;
                for (var lineIndex = 0; lineIndex < linesLength; lineIndex++)
                {
                    var line = TextExample[lineIndex];
                    var charsLength = line.Length;
                    for (var charIndex = 0; charIndex < charsLength; charIndex++)
                        if (line[charIndex] == character)
                            amountOfChar++;
                }
                return amountOfChar;
            }
    

    但不是 foreach 循环:

    [TestSelectManyCount] Found 5861172 characters in 3295,8278ms
    [TestForForIncrement] Found 5861172 characters in 377,0376ms
    [TestForCount] Found 5861172 characters in 1064,9164ms
    [TestForEachWhileIndexOfIncrement] Found 5861172 characters in 1550,894ms
    [TestForEachForEachIncrement] Found 5861172 characters in 473,4347ms
    [TestSumCounts] Found 5861172 characters in 1062,2644ms
    
    using System;
    using System.Diagnostics;
    using System.Linq;
    
    namespace StackOverflow._62505315
    {
        public partial class Program
        {
            public const char CharToBeFound = 'a';
            public const int Iterations = 5000;
    
            static Stopwatch stopWatch = new Stopwatch();
    
            static void Main(string[] args)
            {
                TestSelectManyCount();
                TestForForIncrement();
                TestForCount();
                TestForEachWhileIndexOfIncrement();
                TestForEachForEachIncrement();
                TestSumCounts();
            }
    
            public static void TestSelectManyCount()
            {
                var iterations = Iterations;
                int amountOfChar = 0;
                stopWatch.Start();
                checked
                {
                    while (iterations-- >= 0)
                    {
                        amountOfChar += TextExample.SelectMany(x => x).Count(c => c == CharToBeFound);
                    }
                }
                stopWatch.Stop();
                Console.WriteLine($"[{nameof(TestSelectManyCount)}] Found {amountOfChar} characters in {stopWatch.Elapsed.TotalMilliseconds}ms");
                stopWatch.Reset();
            }
    
            public static void TestForForIncrement()
            {
                var iterations = Iterations;
                int amountOfChar = 0;
                stopWatch.Start();
                checked
                {
                    while (iterations-- >= 0)
                    {
                        var linesLength = TextExample.Length;
                        for (var lineIndex = 0; lineIndex < linesLength; lineIndex++)
                        {
                            var line = TextExample[lineIndex];
                            var charsLength = line.Length;
                            for (var charIndex = 0; charIndex < charsLength; charIndex++)
                                if (line[charIndex] == CharToBeFound)
                                    amountOfChar++;
                        }
                    }
                }
                stopWatch.Stop();
                Console.WriteLine($"[{nameof(TestForForIncrement)}] Found {amountOfChar} characters in {stopWatch.Elapsed.TotalMilliseconds}ms");
                stopWatch.Reset();
            }
    
            public static void TestForCount()
            {
                var iterations = Iterations;
                var amountOfChar = 0;
                stopWatch.Start();
                checked
                {
                    while (iterations-- >= 0)
                    {
                        var lineLength = TextExample.Length;
                        for (var lineIndex = 0; lineIndex < lineLength; lineIndex++)
                        {
                            amountOfChar += TextExample[lineIndex].Count(c => c == CharToBeFound);
                        }
                    }
                }
                stopWatch.Stop();
                Console.WriteLine($"[{nameof(TestForCount)}] Found {amountOfChar} characters in {stopWatch.Elapsed.TotalMilliseconds}ms");
                stopWatch.Reset();
            }
    
            public static void TestForEachWhileIndexOfIncrement()
            {
                var iterations = Iterations;
                var amountOfChar = 0;
                stopWatch.Start();
                checked
                {
                    while (iterations-- >= 0)
                    {
                        foreach (string word in TextExample)
                        {
                            int startIndex = 0;
                            int charIndex = 0;
                            while ((charIndex = word.IndexOf(CharToBeFound, startIndex)) != -1)
                            {
                                startIndex = charIndex + 1;
                                amountOfChar++;
                            }
                        }
                    }
                }
                stopWatch.Stop();
                Console.WriteLine($"[{nameof(TestForEachWhileIndexOfIncrement)}] Found {amountOfChar} characters in {stopWatch.Elapsed.TotalMilliseconds}ms");
                stopWatch.Reset();
            }
    
            public static void TestForEachForEachIncrement()
            {
                var iterations = Iterations;
                int amountOfChar = 0;
                stopWatch.Start();
                checked
                {
                    while (iterations-- >= 0)
                    {
                        foreach (var word in TextExample)
                            foreach (char character in word)
                                if (character == CharToBeFound)
                                    amountOfChar++;
                    }
                }
                stopWatch.Stop();
                Console.WriteLine($"[{nameof(TestForEachForEachIncrement)}] Found {amountOfChar} characters in {stopWatch.Elapsed.TotalMilliseconds}ms");
                stopWatch.Reset();
            }
    
            public static void TestSumCounts()
            {
                var iterations = Iterations;
                int amountOfChar = 0;
                stopWatch.Start();
                checked
                {
                    while (iterations-- >= 0)
                    {
                        amountOfChar += TextExample.Sum(s => s.Count(c => c == CharToBeFound));
                    }
                }
                stopWatch.Stop();
                Console.WriteLine($"[{nameof(TestSumCounts)}] Found {amountOfChar} characters in {stopWatch.Elapsed.TotalMilliseconds}ms");
                stopWatch.Reset();
            }
        }
    }
    
    

    令我惊讶的是,我还发现了一个参考 here,它确实强调了这样一个事实,即 for 循环超出了 foreach 循环的规模

    【讨论】:

    • 有了这个我也得到“运算符'=='不能应用于'char'和'string'类型的操作数”
    • 我不得不假设 CharToCount 是一个字符:char CharToCount = 'b',而 doc1StrArray 是一个字符可枚举数组(类似于 char[]):string[] arrays = new string[] { "testa", "testb" }。请提供完整代码,我们可以具体提供帮助。
    【解决方案4】:

    或者像这样

    private int GetCountOfSpecificCharacter(string[] doc1StrArray, char charToCount)
    {
        int count = 0;
        count = doc1StrArray.Sum(s => s.Count(c => c == charToCount));
        return count;
    }
    

    【讨论】:

    • 我得到“运算符'=='不能应用于'char'和'string'类型的操作数”
    • @B.ClayShannon 你把CharToCount的类型改成char了吗?
    【解决方案5】:

    你也可以使用正则表达式:

    private int GetCountOfSpecificCharacter(string CharToCount)
    {
        return Regex.Matches(string.join("", doc1StrArray), CharToCount).Count;
    }
    

    【讨论】:

      【解决方案6】:

      您可以使用并行 linq 来实现。

          public static int GetBounty(string[] gettysburgLines, char c)
          {
              int count = 0;
              gettysburgLines.AsParallel().ForAll(line => {
                  int q = line.AsParallel().Where(a => a == c).Count();
                  count += q;
              });
              return count;
          }
      

      【讨论】:

        猜你喜欢
        • 2011-08-28
        • 1970-01-01
        • 2012-11-11
        • 1970-01-01
        • 2012-02-18
        • 2013-02-24
        • 2020-10-21
        • 2017-10-09
        • 2010-11-12
        相关资源
        最近更新 更多