构建一个列表中项目计数的字典

13
我有一个包含多个字符串的列表,这些字符串可能会重复出现。我想将此列表转换为一个字典,其中列表项作为键,它们出现的次数作为值。
例如:
List<string> stuff = new List<string>();
stuff.Add( "Peanut Butter" );
stuff.Add( "Jam" );
stuff.Add( "Food" );
stuff.Add( "Snacks" );
stuff.Add( "Philosophy" );
stuff.Add( "Peanut Butter" );
stuff.Add( "Jam" );
stuff.Add( "Food" );

结果将是一个包含以下内容的字典:

"Peanut Butter", 2
"Jam", 2
"Food", 2
"Snacks", 1
"Philosophy", 1

我有一种方法可以做到这一点,但似乎我没有充分利用 C# 3.0 中的好东西。

public Dictionary<string, int> CountStuff( IList<string> stuffList )
{
    Dictionary<string, int> stuffCount = new Dictionary<string, int>();

    foreach (string stuff in stuffList) {
        //initialize or increment the count for this item
        if (stuffCount.ContainsKey( stuff )) {
            stuffCount[stuff]++;
        } else {
            stuffCount.Add( stuff, 1 );
        }
    }

    return stuffCount;
}
5个回答

30
你可以使用 C# 中的 group 子句来实现这个目标。
List<string> stuff = new List<string>();
...

var groups = 
    from s in stuff
    group s by s into g
    select new { 
        Stuff = g.Key, 
        Count = g.Count() 
    };
你也可以直接调用扩展方法,像这样:
var groups = stuff
    .GroupBy(s => s)
    .Select(s => new { 
        Stuff = s.Key, 
        Count = s.Count() 
    });

从这里到把它放进一个 Dictionary<string, int> 中只需要一个短小的跳跃:

var dictionary = groups.ToDictionary(g => g.Stuff, g => g.Count);

你要如何给第一个例子添加orderby? - zadam
@zadam 你可以随时使用 groups = groups.OrderBy(g => g.Stuff); - casperOne

9

我会创建一个专门的列表,由字典支持,添加方法将测试成员资格并在找到后增加计数。

有点像:

public class CountingList
{
    Dictionary<string, int> countingList = new Dictionary<string, int>();

   void Add( string s )
   {
        if( countingList.ContainsKey( s ))
             countingList[ s ] ++;
        else
            countingList.Add( s, 1 );
   }
}

1
Dictionary<string, int> a = stuff.GroupBy(p => p).OrderByDescending(r=>r.Count()).ToDictionary(q => q.Key, q => q.Count());

你可以通过GroupBy然后创建字典来计算每个组的数量。正如性能测试所示,通常有比Linq更高效的方法。我认为你的代码更有效率,而Linq解决方案则更易读和美观。

1
一个想法是给字典一个默认值, 这样你就不必特殊处理第一次出现的情况了。

那只是将处理特殊情况的代码移动到一个单独的类中... - Guffa

0

嗯,实际上没有更好的方法。

也许你可以编写一个LINQ查询来对字符串进行分组,然后计算每个组中有多少个字符串,但那不会像你已经拥有的那样高效。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接