在List 中查找最常出现的数字

使用linq有快速而好的方式吗?

怎么样:

var most = list.GroupBy(i=>i).OrderByDescending(grp=>grp.Count()) .Select(grp=>grp.Key).First(); 

或者在查询语法中:

 var most = (from i in list group i by i into grp orderby grp.Count() descending select grp.Key).First(); 

当然,如果你反复使用它,你可以添加一个扩展方法:

 public static T MostCommon(this IEnumerable list) { return ... // previous code } 

然后你可以使用:

 var most = list.MostCommon(); 

不确定lambda表达式,但我愿意

  1. 对列表进行排序[O(n log n)]

  2. 扫描列表[O(n)]找到最长的游程长度。

  3. 再次扫描[O(n)],报告具有该游程长度的每个数字。

这是因为可能存在多个最常发生的数字。

取自我的回答:

 public static IEnumerable Mode(this IEnumerable input) { var dict = input.ToLookup(x => x); if (dict.Count == 0) return Enumerable.Empty(); var maxCount = dict.Max(x => x.Count()); return dict.Where(x => x.Count() == maxCount).Select(x => x.Key); } var modes = { }.Mode().ToArray(); //returns { } var modes = { 1, 2, 3 }.Mode().ToArray(); //returns { 1, 2, 3 } var modes = { 1, 1, 2, 3 }.Mode().ToArray(); //returns { 1 } var modes = { 1, 2, 3, 1, 2 }.Mode().ToArray(); //returns { 1, 2 } 

我参加了上述方法和David B的 TakeWhile之间的性能测试。

source = {},iterations = 1000000
我的 – 300毫秒,大卫的 – 930毫秒

source = {1},iterations = 1000000
我的 – 1070毫秒,大卫的 – 1560毫秒

source = 100+ ints,2个重复,迭代= 10000
我的 – 300毫秒,大卫的 – 500毫秒

source = 10000随机整数,大约100+重复,迭代= 1000
我的 – 1280毫秒,大卫的 – 1400毫秒

这是另一个答案,似乎很快。 我认为Nawfal的答案通常更快,但这可能会影响长序列。

 public static IEnumerable Mode( this IEnumerable source, IEqualityComparer comparer = null) { var counts = source.GroupBy(t => t, comparer) .Select(g => new { g.Key, Count = g.Count() }) .ToList(); if (counts.Count == 0) { return Enumerable.Empty(); } var maxes = new List(5); int maxCount = 1; for (var i = 0; i < counts.Count; i++) { if (counts[i].Count < maxCount) { continue; } if (counts[i].Count > maxCount) { maxes.Clear(); maxCount = counts[i].Count; } maxes.Add(i); } return maxes.Select(i => counts[i].Key); } 

有人要求找到有关系的解决方案。 这是一个刺:

 int indicator = 0 var result = list.GroupBy(i => i) .Select(g => new {i = g.Key, count = g.Count()} .OrderByDescending(x => x.count) .TakeWhile(x => { if (x.count == indicator || indicator == 0) { indicator = x.count; return true; } return false; }) .Select(x => xi);