【问题标题】:LINQ query to group data between two list collections, populating a nested object (VB.Net)LINQ 查询在两个列表集合之间对数据进行分组,填充嵌套对象 (VB.Net)
【发布时间】:2011-12-15 14:25:10
【问题描述】:

我有这些物品:

Public Class MakeInfo
  Public Property Name As String
  Public Property Description As String
  Public Property Stock As StockInfo
End Class

Public Class ModelInfo
  Public Property Make As String
  Public Property Name As String
  Public Property Description As String
  Public Property Stock As StockInfo
End Class

Public Class StockInfo
  Public Property Count As Integer
  Public Property MinPrice As Double
End Class

使用 LINQ,我需要获取 List(Of MakeInfo) 和 List(Of ModelInfo) 并将 ModelInfo 中的 StockInfo 聚合到 List(Of MakeInfo) 中。

因此,对于每个 MakeInfo,我将计算 MakeInfo.Name = ModelInfo.Make 的所有库存的总数,以及最低价格。

我认为它会是这样的,但是我在访问嵌套对象时遇到了问题,并且不确定是否可以通过单个查询来实现。我尝试了一些变体,但这里是我的目标:

newList = From ma In makeData _
          Group Join mo In modelData _
          On ma.Name Equals mo.Make _
          Into Group _
          Select New MakeInfo With {.Name = m.Name, _
                                    .Description = m.Description, _
                                    .Stock = ?}

【问题讨论】:

  • 请向我们展示您到目前为止所拥有的一切。

标签: vb.net linq list collections aggregate


【解决方案1】:

我最终找到了正确的方法,并且不需要循环迭代:

Dim new_makes = From ma In makes
                Join mo In models On mo.Make Equals ma.Name
                Group By ma.Name, ma.Description
                Into TotalCount = Sum(mo.Stock.Count), LowestPrice = Min(mo.Stock.MinPrice)
                Select New MakeInfo With {.Name = Name, _
                                          .Description = Description, _
                                          .Stock = New StockInfo With {.Count = TotalCount, .MinPrice = LowestPrice}}

我确信这是可能的。

【讨论】:

    【解决方案2】:

    如果您实际上是在尝试修改原始 MakeInfo 对象,则应停止对该组的查询。 newList 将使每个品牌与该品牌的模型组配对。您可以遍历 newList,并为每个品牌将模型聚合到该品牌的 StockInfo

    Dim newList = From ma In makeData _
                  Group Join mo In modelData _
                  On ma.Name Equals mo.Make _
                  Into Group
    For Each g In newList
        g.ma.Stock = g.Group.Aggregate(
                        New StockInfo() With {.MinPrice = Double.NaN},
                        Function(si, model)
                            Return New StockInfo With {
                                         .Count = si.Count + 1,
                                         .MinPrice = If(Double.IsNaN(si.MinPrice) OrElse
                                                        model.Stock.MinPrice < si.MinPrice,
                                                        model.Stock.MinPrice,
                                                        si.MinPrice)}
                        End Function)
    Next
    

    如果您确实想要新实例,只需更改循环以创建新项目,而不是修改现有品牌。

    Dim results As New List(Of MakeInfo)()
    For Each g In newList
        Dim newMake As New MakeInfo()
        newMake.Name = g.ma.Name
        newMake.Description = g.ma.Description
        newMake.Stock = g.Group.Aggregate( same as before )
        results.Add(newMake)
    Next
    

    【讨论】:

    • 我认为可能有一种方法可以在不使用循环的情况下做到这一点,也许我很荒谬(?)。我发现 LINQ 的执行速度并不比只用几个循环完成整个事情并将结果构建到一个新集合要快得多。话虽如此,我已经使用了代码的第二部分并让它工作。感谢您的帮助。
    • 我找到了一个更好的解决方案 - 我添加了一个新的答案。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多