Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/290.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/linq/3.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 林克的数学统计_C#_Linq - Fatal编程技术网

C# 林克的数学统计

C# 林克的数学统计,c#,linq,C#,Linq,我有一组person对象IEnumerable,每个人都有一个age属性 我想生成集合的统计信息,例如此年龄属性的最大值、最小值、平均值、中值等 使用LINQ最优雅的方式是什么?最大值、最小值、平均值是LINQ的一部分: int[] ints = new int[]{3,4,5}; Console.WriteLine(ints.Max()); Console.WriteLine(ints.Min()); Console.WriteLine(ints.Average()); 中位数很简单: 更新

我有一组person对象IEnumerable,每个人都有一个age属性

我想生成集合的统计信息,例如此年龄属性的最大值、最小值、平均值、中值等


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

最大值、最小值、平均值是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并将其存储到一个变量中,或者只是按原样使用它,则效果会更好

var max = persons.Max(p => p.age);
var min = persons.Min(p => p.age);
var average = persons.Average(p => p.age);
在元素数为偶数的情况下修正中值


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

    double? medianAge = people.Median(p => p.Age);
当集合中没有非null值时,此实现返回null,但是如果您不喜欢可为null的返回类型,可以轻松地将其更改为引发异常

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));
}
使用Linq获得中位数适用于偶数或奇数个元素
ints.ElementAtints.Count/2要使中位数正确,需要先对数组进行排序。中位数的实现还假设输入的元素数为奇数。对于{0,1}它将失败。它将给出0而不是0.5。@Mark-AFAIK Median将始终返回源数组中的一个elements@Itay:不,那通常被称为medoid。一个相关的概念是medoid,在这个概念中,结果必须与样本中的一个成员对应。你计算medoid的方法是有偏差的,因为它通常返回一个低于中位数的值,而不是更高的值。如果数据来自数据库,请小心,因为Linq可能会多次读取数据,但是在你的情况下,Linq应该是一个很好的工具,因为你似乎在ram中收集了数据。这一点,枚举源2或3次:第一次是在调用Count时,第二次,可能是第三次是在调用ElementAt时。你完全正确。和LINQ一样,根据您收藏的性质,它的影响从微不足道到令人望而却步。记住优化的规则:规则1:不要这样做。规则2只适用于专家:现在不要这样做。请注意,这个算法不是时间最优的。中位数可以按时计算。@Max您的时间最优解决方案在哪里?
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));
}
int count = persons.Count();

if (count % 2 == 0)
    var median = persons.Select(x => x.Age).OrderBy(x => x).Skip((count / 2) - 1).Take(2).Average();
else
    var median = persons.Select(x => x.Age).OrderBy(x => x).ElementAt(count / 2);