在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表达式,但我愿意
-
对列表进行排序[O(n log n)]
-
扫描列表[O(n)]找到最长的游程长度。
-
再次扫描[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);