管理 IEnumerable.GroupBy() 的更有效方法

发布于 2024-09-14 02:27:51 字数 579 浏览 4 评论 0 原文

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

寻找更好的方法对我的列表进行排序

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

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

我真正想做的是:

// 不确定 GroupBy 选择器函数 def 应该是什么...
Dictionary>> groupByMappings;

我可以用它来分组,例如:

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

正确的方法是什么?

This is a segue to my previous question:

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

Basically, I have a similar situation where I need to do a .GroupBy() on about 40 different fields.

The original code would have used a giant switch statement, but I'd like to know if there's a better way to this.

What I'd really like to do is something like:


// not sure what the GroupBy selector function def should be...

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

which I can use to group by like:


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

What would be the correct way to go about this?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(2

中性美 2024-09-21 02:27:51

您应该能够按对象进行分组:

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

只要您的映射函数返回以下任一值,此功能就可以工作:

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

You should be able to group by object:

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

This will work as long as your mapping functions return either:

  • Instances of built-in types (such as number or strings)
  • Objects that implement IEquatable<T>
  • Objects that implement Equals and GetHashCode correctly
睡美人的小仙女 2024-09-21 02:27:51

嗯,我个人所做的就是构建 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))

这就是您想要的吗?

Well, what I personally do is build up lambda expressions and then applying the final expression to the list.

I use some extension method to Linq.Expression which just wrap something like the following:

<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

And then you can build queries like this:

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))

Is that what you're after?

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文