字符串的集合到字典

Mic*_*eyn 2 c# linq c#-4.0

给定一个有序的字符串集合:

var strings = new string[] { "abc", "def", "def", "ghi", "ghi", "ghi", "klm" };
Run Code Online (Sandbox Code Playgroud)

使用LINQ创建字符串字典到集合中该字符串的出现次数:

IDictionary<string,int> stringToNumOccurrences = ...;
Run Code Online (Sandbox Code Playgroud)

最好一次通过琴弦收集......

Dar*_*rov 8

var dico = strings.GroupBy(x => x).ToDictionary(x => x.Key, x => x.Count());
Run Code Online (Sandbox Code Playgroud)


Jon*_*eet 5

Timwi /达林的建议将在单传过来的原始集合执行此,但它创建用于分组多个缓冲区.LINQ并不是非常擅长这种计数,这样的问题是我编写Push LINQ的最初动机.您可能希望阅读我的博客文章,了解有关为什么LINQ在这里效率不高的详细信息.

推LINQ和相同想法的更令人印象深刻的实现 - Reactive Extensions - 可以更有效地处理这个问题.

当然,如果你真的不太关心额外的效率,请GroupBy回答:)

编辑:我没有注意到你的琴弦是订购的.这意味着你可以更有效,因为你知道,一旦你看到串x,然后y字符串,如果X和Y是不同的,你永远也不会再见到X.LINQ中没有任何内容可以让这更容易,但你可以很容易地自己做:

public static IDictionary<string, int> CountEntries(IEnumerable<string> strings)
{
    var dictionary = new Dictionary<string, int>();

    using (var iterator = strings.GetEnumerator())
    {
        if (!iterator.MoveNext())
        {
            // No entries
            return dictionary;
        }
        string current = iterator.Current;
        int currentCount = 1;
        while (iterator.MoveNext())
        {
            string next = iterator.Current;
            if (next == current)
            {
                currentCount++;
            }
            else
            {
                dictionary[current] = currentCount;
                current = next;
                currentCount = 1;
            }
        }
        // Write out the trailing result
        dictionary[current] = currentCount;
    }
    return dictionary;
}
Run Code Online (Sandbox Code Playgroud)

这是O(n),除了写入值之外,涉及字典查找.另一种实现方式是使用foreachcurrent从null开始的值......但最终在其他几种方式上变得非常狡猾.(我已经尝试过了:)当我需要第一个值的特殊情况处理时,我通常会使用上面的模式.

实际上你可以用LINQ使用Aggregate,但它会非常讨厌.