Is there a way to have a collection of <char, int> pairs which both can have duplicate values in C#?

91 Views Asked by At

I wanna find the count of each character in a row in a given string. For example "aabaccbb" has two 'a', one 'b', one 'a', two 'c', and two 'b'.

I wanna have a collection of <char,int> pairs and the order is important for me. For example above like this: { {'a', 2}, {'b', 1}, {'a', 1}, {'c', 2}, {'b', 2} }

  • "Dictionary<char, int>" can't have duplicate keys (char).
  • "List< <KeyValuePair<char, int> >" is good but the key and value are read-only and I need to modify them.
  • "List<char, List<int>>" isn't suitable too because the order is important for me.

So what can I do?

3

There are 3 best solutions below

8
Cedar On BEST ANSWER

I think you just want to make a class to hold the values for you and then make a list of that type

public class CharCount
{
    public char Char { get; set; }
    public int Count { get; set; }
}

then just create your list of that type

new List<CharCount>()
1
Ibrahim Hamaty On

You can create a class

public class MyChar
{
    public char Char { get; set; }
    public int Num { get; set; }
}

And use it like this.

        string str = "aabaccbb";
        Dictionary<int, MyChar> pairs = new Dictionary<int, MyChar>();

        var chars = str.ToArray();
        int charNo = 0;
        for(int i = 0; i < chars.Length; i++)
        {
            int j = 1;
            while (i + j < chars.Length && chars[i + j] == chars[i])
                j++;

            pairs[charNo] = new MyChar { Char = chars[i], Num = j }; 
            i += j - 1;
            charNo++;
        }
0
NetMage On

Using an extension method that counts runs of items from an IEnumerable<T>, you can just convert to an array to get an ordered collection of items and counts:

var s = "aabaccbb";
var ans = s.CountRuns()
           .ToArray();

Here is the extension:

public static class IEnumerableExt {
    public static IEnumerable<KeyValuePair<T, int>> CountRuns<T>(this IEnumerable<T> items, IEqualityComparer<T> cmp = null) {
        cmp = cmp ?? EqualityComparer<T>.Default;

        using (var itemsEnum = items.GetEnumerator()) {
            if (itemsEnum.MoveNext()) {
                var key = itemsEnum.Current;
                var count = 1;
                while (itemsEnum.MoveNext()) {
                    if (cmp.Equals(key, itemsEnum.Current))
                        ++count;
                    else {
                        yield return new KeyValuePair<T, int>(key, count);
                        key = itemsEnum.Current;
                        count = 1;
                    }
                }
                yield return new KeyValuePair<T, int>(key, count);
            }
        }
    }
}