与Linq的数学统计

我有一组人物对象(IEnumerable),每个人都有一个年龄属性。

我想在这个年龄属性上生成集合的统计数据,例如Max,Min,Average,Median等。

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

max - persons.Max(p => p.age); min - persons.Min(p => p.age); 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; 

这是一个完整的,通用的Median实现,可以正确处理空集合和可空类型。 它具有LINQ友好的Enumerable.Average风格,例如:

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

当集合中没有非null值时,此实现返回null,但如果您不喜欢可为空的返回类型,则可以轻松地将其更改为抛出exception。

 public static double? Median( this IEnumerable source, Func selector) { return source.Select(selector).Median(); } public static double? Median( this IEnumerable 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)); } 

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

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

中位数很容易:

UPDATE

我添加了订单:

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

谨防

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