c# - 如何计算字典中唯一值的出现次数?

标签 c# dictionary distinct

我有一个字典,其中 double 值作为值,字符串作为键。

我想计算这个字典中每个值的出现次数,我想知道这个值(例如重复)。

例如:

key1, 2
key2, 2
key3, 3
key4, 2
key5, 5
key6, 5

我想得到一个列表:

2 - 3 (times)
3 - 1 (once)
5 - 2 (twice)

我该怎么做?

最佳答案

首先要注意的是,您实际上并不关心字典的键。因此,第一步是忽略它们,因为它们与手头的任务无关。我们将使用 Values字典的属性,并且工作与任何其他整数集合(或者实际上我们可以比较相等性的任何其他类型的任何其他可枚举)几乎相同。

有两种常见的方法可以解决这个问题,这两种方法都值得了解。

第一个使用另一个字典来保存值的计数:

//Start with setting up the dictionary you described.
Dictionary<string, int> dict = new Dictionary<string, int>{
    {"key1", 2},
    {"key2", 2},
    {"key3", 3},
    {"key4", 2},
    {"key5", 5},
    {"key6", 5}
};
//Create a different dictionary to store the counts.
Dictionary<int, int> valCount = new Dictionary<int, int>();
//Iterate through the values, setting count to 1 or incrementing current count.
foreach(int i in dict.Values)
    if(valCount.ContainsKey(i))
        valCount[i]++;
    else
        valCount[i] = 1;
//Finally some code to output this and prove it worked:
foreach(KeyValuePair<int, int> kvp in valCount)//note - not sorted, that must be added if needed
    Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value);

希望这非常简单。另一种方法更复杂,但有一些优点:

//Start with setting up the dictionary you described.
Dictionary<string, int> dict = new Dictionary<string, int>{
    {"key1", 2},
    {"key2", 2},
    {"key3", 3},
    {"key4", 2},
    {"key5", 5},
    {"key6", 5}
};
IEnumerable<IGrouping<int, int>> grp = dict.Values.GroupBy(x => x);
//Two options now. One is to use the results directly such as with the
//equivalent code to output this and prove it worked:
foreach(IGrouping<int, int> item in grp)//note - not sorted, that must be added if needed
    Console.WriteLine("{0} - {1}", item.Key, item.Count());
//Alternatively, we can put these results into another collection for later use:
Dictionary<int, int> valCount = grp.ToDictionary(g => g.Key, g => g.Count());
//Finally some code to output this and prove it worked:
foreach(KeyValuePair<int, int> kvp in valCount)//note - not sorted, that must be added if needed
    Console.WriteLine("{0} - {1}", kvp.Key, kvp.Value);

(我们可能会使用 var 而不是冗长的 IEnumerable<IGrouping<int, int>> ,但在解释代码时值得精确)。

直接比较,此版本较差 - 理解起来更复杂且效率更低。但是,学习这种方法可以使同一技术有一些简洁高效的变体,因此值得研究。

GroupBy()采用一个枚举并创建另一个包含键值对的枚举,其中值也是一个枚举。 λ x => x意味着它分组的依据是它本身,但是我们可以灵活地使用不同的分组规则。 grp的内容看起来有点像:

{
  {Key=2, {2, 2, 2}}
  {Key=3, {3}}
  {Key=5, {5, 5}}
}

因此,如果我们为每个组循环遍历此 an,我们将取出 Key并调用Count()在组上,我们得到了我们想要的结果。

现在,在第一种情况下,我们在一次 O(n) 遍中建立我们的计数,而在这里我们在 O(n) 遍中建立组,然后在第二个 O(n) 中获得计数通过,使其效率大大降低。它也有点难以理解,所以为什么要提它呢?

好吧,首先是一旦我们理解了它,我们就可以改变界限:

IEnumerable<IGrouping<int, int>> grp = dict.Values.GroupBy(x => x);
foreach(IGrouping<int, int> item in grp)
    Console.WriteLine("{0} - {1}", item.Key, item.Count());

进入:

foreach(var item in dict.Values.GroupBy(x => x))
  Console.WriteLine("{0} - {1}", item.Key, item.Count());

这非常简洁,而且很地道。如果我们想继续对值计数对做一些更复杂的事情,那就特别好,因为我们可以将其链接到另一个操作中。

将结果放入字典的版本可以更简洁:

var valCount = dict.Values.GroupBy(x => x).ToDictionary(g => g.Key, g => g.Count());

在那里,您的整个问题都在一个简短的行中得到了回答,而不是第一个版本的 6(删除评论)。

(有些人可能更愿意将 dict.Values.GroupBy(x => x) 替换为 dict.GroupBy(x => x.Value),一旦我们在其上运行 Count() 将获得完全相同的结果。如果您不能立即确定原因,请尝试解决)。

另一个优势是我们使用 GroupBy 具有更大的灵 active 在其他情况下。由于这些原因,习惯使用 GroupBy 的人很可能从一行简洁的 dict.Values.GroupBy(x => x).ToDictinary(g => g.Key, g => g.Count()); 开始如果它被证明是一个性能热点,然后更改为第一个版本的更冗长但更有效的形式(我们在新字典中增加运行总计)。

关于c# - 如何计算字典中唯一值的出现次数?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8459928/

相关文章:

c# - 范围内数字的 BinarySearch 限制

c# - 如何检查 Windows 注册表在 .NET Core 应用程序中是否可用?

javascript - 在 JavaScript 中按值对字典进行排序

C# 从列表中获取可能的 DISTINCT 组合

r - 如何使用 DPLYR 汇总一列中组的唯一值?

C# "invalid providertype"与 Google 服务帐户

c# - 如何发现 Socket.Select() 报错的原因

python - 如何防止通过 for 循环覆盖字典中的数据

python - 如何循环遍历此 Python 字典并搜索是否存在值

javascript - 如何计算mongodb中两个集合中一个字段的不同值的数量