在List <int> </int>中查找最常出现的数字

时间:2008-12-10 12:55:29

标签: c# linq list

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

5 个答案:

答案 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表达式,但我会

  1. 对列表[O(n log n)]

  2. 进行排序
  3. 扫描列表[O(n)],查找最长的游程长度。

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

  5. 这是因为可能存在多个最常出现的数字。

答案 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);