如何将此循环优化为一个linq查询完全删除循环调用?

时间:2016-05-04 16:03:17

标签: asp.net linq query-optimization jqplot linq-to-objects

我有这个循环逐个构建这些IEnumerables,我希望能够优化它,以便它可以一次调用并构建所有这些IEnumerables IEnumerable而不是循环必须执行的列表。该代码按月对FilteredCases(一年中不同类型树木的情况)进行分组,并计算该月份与全年相比的树木百分比。我的问题是,我每年都会单独执行此操作,并希望通过将正确的数据组合在一起,在一个LINQ调用中执行此操作。

以下是代码:

        var seriesDataLineList = new List<IEnumerable<SeriesDataPointArray>>();

        foreach (var tree in trees)
        {
            IEnumerable<SeriesDataPointArray> seriesDataLine = months.Select(month => new SeriesDataPointArray()
            {
                X = month.LookupMonthName,
                Y = new object[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
            });

            seriesDataLineList.Add(seriesDataLine);
        }

我尝试使用LINQ执行此操作:

var test = from fc in FilteredCases
           group fc by new { fc.Tree, fc.Month }
           into casesGrouped
           orderby casesGrouped.Key.Tree
           select new { casesGrouped.Key.Tree, casesGrouped.Key.Month, count = casesGrouped.Count() };

但我不确定如何将这些内容合并为一个IEnuerable<SeriesDataPointArray>

1 个答案:

答案 0 :(得分:0)

你上面提到的是循环和linq的混合,因为你将迭代与基于集合的逻辑混合在一起会让人感到困惑。如果将代码扩展为只是循环,您可能会发现更容易转换为linq。

作为所有循环

        var seriesDataLineList = new List<SeriesDataPointArray>();
        foreach (var tree in trees)
        {
            foreach (var month in months)
            {
                var seriesDataLine = new SeriesDataPointArray()
                {
                    X = month.LookupMonthName,
                    Y = new double[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
                };
                seriesDataLineList.Add(seriesDataLine);
            };
        }

在所有循环中获得代码后,转换为linq非常简单。嵌套循环在功能上等同于笛卡尔积,在句法上可以通过多个不相关的语句来实现。

        var results = from tree in trees
                      from month in months
                      select new SeriesDataPointArray()
                      {
                          X = month.LookupMonthName,
                          Y = new double[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
                      };

或者在lambda中,多个嵌套的select语句。你需要在某处使用SelectMany()来展平嵌套集合。

        var results = trees.Select(tree =>
            months.Select(month =>
                new SeriesDataPointArray()
                {
                    X = month.LookupMonthName,
                    Y = new double[] { Math.Round(FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId && fc.LookupMonthId == month.LookupMonthId) / (double)FilteredCases.Count(fc => fc.LookupTreeId == tree.LookupTreeId) * 100, 0) }
                }
            )
        ).SelectMany(x => x);