代码之家  ›  专栏  ›  技术社区  ›  leora Matt Lacey

使用Linq的数学统计

  •  14
  • leora Matt Lacey  · 技术社区  · 14 年前

    我收集了 对象(IEnumerable),每个人都有一个 财产。

    我想生成集合的统计信息,比如Max、Min、Average、Median等。

    使用LINQ最优雅的方法是什么?

    3 回复  |  直到 11 年前
        1
  •  28
  •   Sai Manoj Kumar Yadlapati    6 年前
    var max = persons.Max(p => p.age);
    var min = persons.Min(p => p.age);
    var average = persons.Average(p => p.age);
    

    偶数元素时中值的修正

    int count = persons.Count();
    var orderedPersons = persons.OrderBy(p => p.age);
    float median = orderedPersons.ElementAt(count/2).age + orderedPersons.ElementAt((count-1)/2).age;
    median /= 2;
    
        2
  •  35
  •   Rand Scullard    13 年前

    这里是一个完整的、通用的中值实现,可以正确处理空集合和可为空类型。它以可枚举的方式对LINQ友好。平均值,例如:

        double? medianAge = people.Median(p => p.Age);
    

    当集合中没有非空值时,此实现将返回空值,但是如果您不喜欢可为空的返回类型,可以很容易地将其更改为引发异常。

    public static double? Median<TColl, TValue>(
        this IEnumerable<TColl> source,
        Func<TColl, TValue>     selector)
    {
        return source.Select<TColl, TValue>(selector).Median();
    }
    
    public static double? Median<T>(
        this IEnumerable<T> source)
    {
        if(Nullable.GetUnderlyingType(typeof(T)) != null)
            source = source.Where(x => x != null);
    
        int count = source.Count();
        if(count == 0)
            return null;
    
        source = source.OrderBy(n => n);
    
        int midpoint = count / 2;
        if(count % 2 == 0)
            return (Convert.ToDouble(source.ElementAt(midpoint - 1)) + Convert.ToDouble(source.ElementAt(midpoint))) / 2.0;
        else
            return Convert.ToDouble(source.ElementAt(midpoint));
    }
    
        3
  •  10
  •   Aliostad    14 年前

    Max,Min,Average是Linq的一部分:

    int[] ints = new int[]{3,4,5};
    Console.WriteLine(ints.Max());
    Console.WriteLine(ints.Min());
    Console.WriteLine(ints.Average());
    

    中位数很容易:

    ints.OrderBy(x=>x).Skip(ints.Count()/2).First();
    

    当心

    所有这些操作都是在一个循环中完成的。例如,ints.Count()是一个循环,因此如果您已经获得ints.Length并存储到变量中,或者只是按原样使用它,就更好了。