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# 使用LINQ返回不同值的平均值_C#_Linq - Fatal编程技术网

C# 使用LINQ返回不同值的平均值

C# 使用LINQ返回不同值的平均值,c#,linq,C#,Linq,我对LINQ没有太多经验,而且我很难使用LINQ根据不同列中的不同值提取ListView列的平均值、模式值和中值 例如,考虑这些数据: ReportID TAT Col3 Col4 etc... -------- --- ---- ---- ------- 80424 9 1 7 ... 80424 9 2 3 ... 80424 9 2 2 ... 80423 5 1

我对LINQ没有太多经验,而且我很难使用LINQ根据不同列中的不同值提取ListView列的平均值、模式值和中值

例如,考虑这些数据:

ReportID  TAT  Col3  Col4  etc...
--------  ---  ----  ----  -------
80424     9    1     7     ...
80424     9    2     3     ...
80424     9    2     2     ...
80423     5    1     5     ...
80425     4    1     5     ...
80423     7    1     4     ...
82541     7    1     5     ...
要提取TAT(周转时间)大于5天的不同报告的计数,我使用以下方法:

int countDistinctReports = (from ListViewItem itm in lvList.Items
                            where itm.SubItems[1].Text) > 5
                            select itm.SubItems[0].Text
                           ).Distinct().Count();
countdistinctreport
的值为3

要提取这些报告的最小TAT,我使用以下方法:

string minVal = (from ListViewItem itm in lvList.Items
             where itm.SubItems[1].Text) > 5
             select itm.SubItems[1].Text
            ).Min();
minVal
的值为7

但是,我不知道如何编写LINQ表达式来计算TAT大于5的不同报告的平均、模式和中值TAT。在上述示例中,平均值应为(9+7+7)/3=7.67。模式应为7


有人能帮忙吗?非常感谢。

您应该使用GroupBy方法

var groups = myList.GroupBy(e=>e.Key);//here key is your TAT
然后,如果要计算组数:

var count = groups.Count();
如果要获得所有组的最小值:

var mins = groups.Select(g=>g.Min());
如果要获取并保留关键信息:

var keyedMins = groups.Select(g=>new{K=g.Key,Min=g.Min()};

与average和other相同:)

对于average,还有一个名为LINQ的方法。但是,您必须将字符串转换为数字才能有效地使用数字算术

var minVal = (from ListViewItem itm in lvList.Items
             where itm.SubItems[1].Text) > 5
             select Convert.ToInt32(itm.SubItems[1].Text)
            ).Average();
但是,对于中间带或模式,没有此类方法。你必须创造你自己的

例如,对于中位数:

string subList = (from ListViewItem itm in lvList.Items
             where itm.SubItems[1].Text) > 5
             select Convert.ToIn32(itm.SubItems[1].Text)
            ).OrderBy(x => x).ToList();
var median = subList[subList.Count / 2];

这将首先创建一个包含所有项目的列表,其值大于
5
,并取中间的值。

以下是仅使用linq 1行程序重现并解决的问题:

using System;
using System.Linq;

namespace StackOverflow_StatisticsLinq
{
    class Program
    {
        static void Main(string[] args)
        {
            var reports = new int[][]
            {
                new int[] {80424, 9, 1, 7},
                new int[] {80424, 9, 2, 3},
                new int[] {80424, 9, 2, 2},
                new int[] {80423, 5, 1, 5},
                new int[] {80425, 4, 1, 5},
                new int[] {80423, 7, 1, 4},
                new int[] {80541, 7, 1, 5}
            };

            var reportsTat5Plus = (
                    from int[] r in reports
                    where r[1] > 5
                    orderby r[1] descending
                    select r)
                .GroupBy(r => r[0])
                .Select(r => r.First()); // ensure ids are distinct
            
            var average = reportsTat5Plus.Select(r => r[1]).Average();
            
            var mode = reportsTat5Plus.GroupBy(v => v)
                .OrderByDescending(g => g.Count())
                .First()
                .Select(r => r[1])
                .First();
            
            var median = reportsTat5Plus.Count() % 2 == 1
                ? reportsTat5Plus.Skip(reportsTat5Plus.Count() / 2 + 1).Select(r => r[1]).First()
                : reportsTat5Plus.Skip(reportsTat5Plus.Count() / 2 - 1).Take(2).Select(r => r[1]).Average();

            Console.WriteLine($"Average: {average}");
            Console.WriteLine($"mode: {mode}");
            Console.WriteLine($"median: {median}");
            Console.ReadKey();
        }
    }
}

好的解决方案,尽管考虑为中位数,模式扩展方法,以避免内联的复杂性和更高的耐久性。注意,我使用了一个衬里,以显示它可以完成/如何。我不会为生产编写这样的代码:对于我的口味来说,一行代码发生的事情太多了。模式和中值的扩展方法可能是一个非常好的主意。