Более эффективный способ управления IEnumerable.GroupBy () - PullRequest
1 голос
/ 13 августа 2010

Это переход к моему предыдущему вопросу:

В поисках лучшего способа сортировки моего списка

В принципе, у меня похожая ситуация, когда мне нужно сделать .GroupBy () для примерно 40 различных полей.

В оригинальном коде использовался бы гигантский оператор switch, но я хотел бы знать, есть ли лучший способ для этого.

То, что я действительно хотел бы сделать, это что-то вроде:

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

, который я могу использовать для группировки по:

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

Как правильно поступить?

Ответы [ 2 ]

1 голос
/ 13 августа 2010

Вы должны иметь возможность группировать по object:

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

Это будет работать до тех пор, пока ваши функции отображения не вернутся:

  • Экземпляры встроенных типов (например, число или строки)
  • Объекты, которые реализуют IEquatable<T>
  • Объекты, которые правильно реализуют Equals и GetHashCode
0 голосов
/ 13 августа 2010

Ну, лично я создаю лямбда-выражения и затем применяю окончательное выражение к списку.

Я использую какой-то метод расширения для 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))

Это то, что вы ищете?

...