使用linq有快速而好的方法吗?
答案 0 :(得分:70)
怎么样:
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<T>(this IEnumerable<T> list)
{
return ... // previous code
}
然后你可以使用:
var most = list.MostCommon();
答案 1 :(得分:4)
不确定lambda表达式,但我会
对列表[O(n log n)]
扫描列表[O(n)],查找最长的游程长度。
再次扫描[O(n)],报告每个具有该游程长度的号码。
这是因为可能存在多个最常出现的数字。
答案 2 :(得分:3)
取自我的回答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 }
我参加了上述方法和David B's 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毫秒
答案 3 :(得分:1)
这是另一个答案,似乎很快。我认为Nawfal's answer通常更快,但这可能会影响长序列。
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);
}
答案 4 :(得分:0)
有人要求找到有关系的解决方案。这是对此的抨击:
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);