代码之家  ›  专栏  ›  技术社区  ›  Philip Atz

嵌套IGroupings的SelectMany类扩展方法

  •  0
  • Philip Atz  · 技术社区  · 1 年前

    假设我有一个可枚举项,我已经对其进行了应用 .GroupBy() 两次以嵌套结束 IGroupings :

    IEnumerable<IGrouping<TOuterKey, IGrouping<TInnerKey, TElement>>> source = enumerable.GroupBy(o => o.InnerKey).GroupBy(g => g.OuterKey);
    

    对于嵌套 IEnumerables ,很容易申请 .SelectMany() 得到一个扁平 IEnumerable 所有的结果。For I分组 然而,这并不是那么简单。假设我想要一个通用的扩展方法来实现这一点:

    public static IEnumerable<IGrouping<TResultKey, TResultElement>> SelectMany<TOuterKey, TInnerKey, TInputElement, TResultKey, TResultElement>(
        this IEnumerable<IGrouping<TOuterKey, IGrouping<TInnerKey, TInputElement>>> source,
        Func<IGrouping<TOuterKey, IGrouping<TInnerKey, TInputElement>>, TResultKey> keySelector,
        Func<TOuterKey, TInnerKey, TInputElement, TResultElement> valueSelector)
    

    我该如何创建它?

    0 回复  |  直到 1 年前
        1
  •  0
  •   Philip Atz    1 年前

    我在发布问题和答案之间留出了一些时间,给任何想试试这个的人一个机会,但现在我会给你我的答案:

    public static IEnumerable<IGrouping<TResultKey, TResultElement>> GroupSelectMany<TOuterKey, TInnerKey, TSourceElement, TResultKey, TResultElement>(
        this IEnumerable<IGrouping<TOuterKey, IGrouping<TInnerKey, TSourceElement>>> source,
        Func<IGrouping<TOuterKey, IGrouping<TInnerKey, TSourceElement>>, TResultKey> keySelector,
        Func<TOuterKey, TInnerKey, TSourceElement, TResultElement> elementSelector)
    {
        elementSelector = elementSelector ?? ((outerKey, innerKey, element) => (TResultElement)(object)element);
        
        return source.SelectMany(
            gg => new IGrouping<TResultKey, TResultElement>[]
            {
                new Grouping<TResultKey, TResultElement>(
                    keySelector(gg),
                    gg.SelectMany(
                        g => g.Select(
                            o => elementSelector(gg.Key, g.Key, o))))
            }); 
    }
    

    你还需要一个IGrouping的实现,我已经找到了 here ,但我只包括 private 出于封装目的:

    private class Grouping<TKey, TElement> : List<TElement>, IGrouping<TKey, TElement>
    {
        public Grouping(TKey key) : base() => Key = key;
        public Grouping(TKey key, int capacity) : base(capacity) => Key = key;
        public Grouping(TKey key, IEnumerable<TElement> collection)
            : base(collection) => Key = key;
        public TKey Key { get; }
    }