【问题标题】:A more efficient way to manage IEnumerable.GroupBy()管理 IEnumerable.GroupBy() 的更有效方法
【发布时间】:2011-03-29 12:06:48
【问题描述】:

这是我上一个问题的延续:

Looking for a better way to sort my List<T>

基本上,我有类似的情况,我需要在大约 40 个不同的字段上执行 .GroupBy()。

原始代码会使用一个巨大的 switch 语句,但我想知道是否有更好的方法。

我真正想做的是:

// not sure what the GroupBy selector function def should be...
Dictionary<PortfolioMapping, Func<Holding, ???>> groupByMappings;

我可以用它来分组:

myPortfolioHoldings.GroupBy(groupByMaping[frmGroupBySelector.SelectedColumn]);

解决这个问题的正确方法是什么?

【问题讨论】:

    标签: c# .net-3.5 c#-3.0 lambda


    【解决方案1】:

    嗯,我个人所做的是构建 lambda 表达式,然后将最终表达式应用于列表。

    我对 Linq.Expression 使用了一些扩展方法,它只包含如下内容:

    <System.Runtime.CompilerServices.Extension()> _
    Public Function Compose(Of T)(ByVal first As Expressions.Expression(Of T), ByVal second As Expressions.Expression(Of T), ByVal merge As Func(Of Expressions.Expression, Expressions.Expression, Expressions.Expression)) As Expressions.Expression(Of T)
    
        '' build parameter map (from parameters of second to parameters of first)
        Dim map = first.Parameters.[Select](Function(f, i) New With {f, .s = second.Parameters(i)}).ToDictionary(Function(p) p.s, Function(p) p.f)
    
        '' replace parameters in the second lambda expression with parameters from the first
        Dim secondBody = ParameterRebinder.ReplaceParameters(map, second.Body)
    
        '' applycomposition of lambda expression bodies to parameters from the first expression 
            Return Expressions.Expression.Lambda(Of T)(merge(first.Body, secondBody), first.Parameters)
        End Function
    
    <System.Runtime.CompilerServices.Extension()> _
    Public Function [And](Of T)(ByVal first As Expressions.Expression(Of Func(Of T, Boolean)), ByVal second As Expressions.Expression(Of Func(Of T, Boolean))) As Expressions.Expression(Of Func(Of T, Boolean))
        Return first.Compose(second, AddressOf Expressions.Expression.And)
    End Function
    

    然后你可以像这样构建查询:

    Dim MyQuery as Linq.Expressions.Expression(Of System.Func(Of MyListDataType, Boolean))
    Dim MyGroupingExpression as Linq.Expressions.Expression(Of System.Func(Of MyListDataType, Boolean))
    
    Dim MyQuery = Function(x) x.SomeValue = SomeExpectedValue
    Select case SomeOtherVariable
        Case Option1
            Dim MyGroupingExpression = <blah>
        Case Option2
            Dim MyGroupingExpression = <blah>
    End Select
    
    Dim Results = MyList.Where(MyQuery.And(GroupingExpression))
    

    这就是你所追求的吗?

    【讨论】:

      【解决方案2】:

      你应该可以按object分组:

      Dictionary<PortfolioMapping, Func<Holding, object>> groupByMappings;
      

      只要您的映射函数返回,这将起作用:

      • 内置类型的实例(例如数字或字符串)
      • 实现IEquatable&lt;T&gt;的对象
      • 正确实现EqualsGetHashCode 的对象

      【讨论】:

      • 谢谢蒂姆!将测试和确认,但看起来像我要找的。​​span>
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-05-07
      • 2010-09-10
      • 2014-08-09
      • 2013-04-19
      • 2018-01-15
      • 1970-01-01
      相关资源
      最近更新 更多