C# 查找 List<int> 中出现次数最多的数字
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/355945/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Find the most occurring number in a List<int>
提问by
Is there a quick and nice way using linq?
有没有一种使用 linq 的快速而好的方法?
采纳答案by Marc Gravell
How about:
怎么样:
var most = list.GroupBy(i=>i).OrderByDescending(grp=>grp.Count())
.Select(grp=>grp.Key).First();
or in query syntax:
或在查询语法中:
var most = (from i in list
group i by i into grp
orderby grp.Count() descending
select grp.Key).First();
Of course, if you will use this repeatedly, you could add an extension method:
当然,如果你会重复使用这个,你可以添加一个扩展方法:
public static T MostCommon<T>(this IEnumerable<T> list)
{
return ... // previous code
}
Then you can use:
然后你可以使用:
var most = list.MostCommon();
回答by Mike Dunlavey
Not sure about the lambda expressions, but I would
不确定 lambda 表达式,但我会
Sort the list [O(n log n)]
Scan the list [O(n)] finding the longest run-length.
Scan it again [O(n)] reporting each number having that run-length.
对列表进行排序 [O(n log n)]
扫描列表 [O(n)] 找到最长的游程长度。
再次扫描 [O(n)] 报告每个具有该游程长度的数字。
This is because there could be more than one most-occurring number.
这是因为出现次数最多的数字可能不止一个。
回答by Amy B
Someone asked for a solution where there's ties. Here's a stab at that:
有人要求解决有联系的解决方案。这是一个尝试:
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 => x.i);
回答by nawfal
Taken from my answer here:
摘自我在这里的回答:
public static IEnumerable<T> Mode<T>(this IEnumerable<T> input)
{
var dict = input.ToLookup(x => x);
if (dict.Count == 0)
return Enumerable.Empty<T>();
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 }
I went for a performance test between the above approach and David B'sTakeWhile
.
我在上述方法和David B 的TakeWhile
.
source = { }, iterations = 1000000
mine - 300 ms, David's - 930 mssource = { 1 }, iterations = 1000000
mine - 1070 ms, David's - 1560 mssource = 100+ ints with 2 duplicates, iterations = 10000
mine - 300 ms, David's - 500 mssource = 10000 random ints with about 100+ duplicates, iterations = 1000
mine - 1280 ms, David's - 1400 ms
源 = { },迭代 = 1000000
我的 - 300 毫秒,大卫的 - 930 毫秒源 = { 1 },迭代 = 1000000
我的 - 1070 毫秒,大卫的 - 1560 毫秒源 = 100+ 整数,有 2 个重复,迭代 = 10000
我的 - 300 毫秒,大卫的 - 500 毫秒源 = 10000 个随机整数,大约有 100 多个重复,迭代 = 1000
我的 - 1280 毫秒,大卫的 - 1400 毫秒
回答by Jodrell
Here is another answer, which seems to be fast. I think Nawfal's answeris generally faster but this might shade it on long sequences.
这是另一个答案,似乎很快。我认为Nawfal 的答案通常更快,但这可能会影响长序列。
public static IEnumerable<T> Mode<T>(
this IEnumerable<T> source,
IEqualityComparer<T> 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<T>();
}
var maxes = new List<int>(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);
}