简体   繁体   中英

How can I retrieve the count of a certain character in a string array?

I have this code to try to get a count of how many of the passed-in characters occurs in a string array:

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

...called like so:

iCountOfCommasInDoc1 = GetCountOfSpecificCharacter(",");

...but it doesn't work. It finds no commas, for example, in the following case, although the document certainly does contain commas.

在此处输入图像描述

UPDATE

Both are working - Roman's suggestion and Teroneko's:

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

...but I don't know which one is better/more efficient.

private int GetCountOfSpecificCharacter(char charToCount)
{
    int count = 0;
    foreach (var word in doc1StrArray)
        foreach (char character in word)
           if (character == charToCount)
               count++;
    return count;
}

@Jawad is right. You can do something like this to accomplimish your goal:

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

This selects any character in each array item and returns them as one IEnumerable<char> . When you know apply .Count(..) on it, you are counting against each character.

Edit : I made some tests and it seems that the for-loop is the fastest

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

but not the foreach-loop:

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

For my surprise I also found a reference here that does underline the fact, that the for-loop is outscaling the foreach-loop

This is a sample of what you can use to iterate over an array of strings to check the number of times a character appears in the string and then sum it all up.

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

During the comparison, you can convert the character being iterated to a string for a proper string.Equals(string) comparison. Reason you want to convert it to a string is because character 'a' is Not equal to a string "a". If you want to do a character comparison, see the character compare method below (but note characters should be compared with characters and strings with strings.).

This can be your method to count,

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

Or like this

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

You can also make use of Regex:

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

You could implement with parallel 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;
    }

just use:

var ad = Array.FindAll(yourArray,u=>u.Equals(passedChar).Length

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM