代码之家  ›  专栏  ›  技术社区  ›  jsmith

LINQ(模式)中的返回模式平均值

  •  1
  • jsmith  · 技术社区  · 14 年前

    Increment    Value
    .02            1
    .04            1
    .06            1
    .08            2
    .10            2
    

    我需要返回哪个值出现最多“CopyMost”。在本例中,值是1。现在我计划为IEnumerable编写一个扩展方法,以实现整数值的扩展。在Linq中是否有一些东西已经很容易做到这一点了?还是我最好写一个类似这样的扩展方法

    records.CopyMost(x => x.Value);
    

    编辑

    看起来我在找模态平均值。我已经提供了一个更新的答案,允许一个平局的条件。它的本意是这样使用的,而且是通用的。

    records.CopyMost(x => x.Value, x => x == 0);
    

    在本例中,x.Value将是一个int,如果0的计数与1和3的计数相同,它将在0上断开。

    3 回复  |  直到 7 年前
        1
  •  4
  •   Jon Skeet    14 年前

    好吧,这里有一个选择:

    var query = (from item in data
                 group 1 by item.Value into g
                 orderby g.Count() descending
                 select g.Key).First();
    

    基本上我们用的是 GroupBy 按价值分组-但我们对每个组感兴趣的是 集团和 (原值)。我们按大小对组进行排序,并取第一个元素(元素最多的元素)。

        2
  •  2
  •   Matthew Dresser    14 年前

    乔恩赢了我,但你要找的术语是 Modal Average .

    如果我认为你需要的是模态平均值,那么下面的方法就可以了:

    var i = (from t in data
             group t by t.Value into aggr
             orderby aggr.Count() descending
             select aggr.Key).First();
    
        3
  •  0
  •   jsmith    7 年前

    多年来,我的代码中多次更新了此方法。它已经成为一种非常重要的方法,而且与过去大不相同。我想提供最新的版本,以防有人想添加CopyMost或Modal Average作为linq扩展。

    有一件事我不认为我需要的是某种决胜局。我现在重载了这个方法以包含一个tiebreaker。

    public static K CopyMost<T, K>(this IEnumerable<T> records, Func<T, K> propertySelector, Func<K, bool> tieBreaker)
    {
        var grouped = records.GroupBy(x => propertySelector(x)).Select(x => new { Group = x, Count = x.Count() });
        var maxCount = grouped.Max(x => x.Count);
        var subGroup = grouped.Where(x => x.Count == maxCount);
    
        if (subGroup.Count() == 1)
            return subGroup.Single().Group.Key;
        else
            return subGroup.Where(x => tieBreaker(x.Group.Key)).Single().Group.Key;
    }
    

    以上假设用户输入了合法的断开连接条件。您可能需要检查tiebreaker是否返回有效值,如果不是,则抛出异常。这是我的常规方法。

    public static K CopyMost<T, K>(this IEnumerable<T> records, Func<T, K> propertySelector)
    {
        return records.GroupBy(x => propertySelector(x)).OrderByDescending(x => x.Count()).Select(x => x.Key).First();
    }