繁体   English   中英

具有结果选择器重载的Linq的GroupBy方法有什么用?

[英]What are the uses for Linq's GroupBy method with resultselector overload?

在MSDN上,我发现Enumerable.GroupBy方法的以下重载:

public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(
this IEnumerable<TSource> source,
Func<TSource, TKey> keySelector,
Func<TSource, TElement> elementSelector,
Func<TKey, IEnumerable<TElement>, TResult> resultSelector)

以及以下示例:

    List<Pet> petsList =
    new List<Pet>{ new Pet { Name="Barley", Age=8.3 },
                   new Pet { Name="Boots", Age=4.9 },
                   new Pet { Name="Whiskers", Age=1.5 },
                   new Pet { Name="Daisy", Age=4.3 } };

    var query = petsList.GroupBy(
    pet => Math.Floor(pet.Age), //keySelector
    pet => pet.Age,             //elementSelector
    (baseAge, ages) => new      //resultSelector
    {
        Key = baseAge,
        Count = ages.Count(),
        Min = ages.Min(),
        Max = ages.Max()
    });

尽管我了解此代码的工作原理,但我无法想到它的实际用法。 正如我现在看到的那样,这将返回一个Enumerable ,其代码末尾定义了匿名类型的元素。 但是,为什么GroupBy方法会返回未分组的枚举? 不能通过使用Select,OrderBy等来完成? 还是此重载的主要目的是自己定义Dictionary作为TResult一部分?

以下两个查询将产生相同的结果。

var queryA = source
    .GroupBy(x => x.Id)
    .Select(g => new { Id = g.Key, Count = g.Count() });

var queryB = source
    .GroupBy(x => x.Id, (key, g) => new { Id = key, Count = g.Count() });

不同之处在于,第一个查询必须为每个组实例化IGrouping<TKey, TElement> ,而第二个查询则不必。 在这种情况下,您应该首选queryB

是的,它没有执行Select()无法完成的任何操作。 我们甚至可以将其实现为:

public static IEnumerable<TResult> GroupBy<TSource, TKey, TElement, TResult>(this IEnumerable<TSource> source, Func<TSource, TKey> keySelector, Func<TSource, TElement> elementSelector, Func<TKey, IEnumerable<TElement>, TResult> resultSelector)
{
  return source.GroupBy(keySelector, elementSelector).Select(grp => resultSelector(grp.Key, grp));
}

/* Repeat in Queryable for IQueryable */

但是,首先,它不是以这种方式实现的,并且这种相对常见的情况得到了更有效的处理。

其次,我怀疑更大的影响力(但不能肯定地说)是IQueryable版本类似于许多SQL组构造。 确实,对于SQL的GROUP BY ,在大多数情况下,我们必须将聚合函数与未包含在GROUP BY中的那些选定项目一起使用。 考虑:

SELECT FLOOR(age), COUNT(ALL age), MIN(age), MAX(age)
FROM Pets
GROUP BY FLOOR(age)

这几乎等同于您引用的示例中基于列表的操作。

因此,有意义的是让Queryable.GroupBy()重载带有resultSelector参数,并且当它们在Queryable作用于IQueryable ,相应的方法必须在Enumerable作用于IEnumerable

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM