Linq使用外部集合的内部集合中的count来连接标记列表

时间:2011-04-03 06:39:23

标签: linq list linq-to-objects observablecollection generic-collections

我正在尝试编写一个Linq查询,该查询可以从父产品的外部集合中连接内部标记集合,并返回一个标签集合,其中合并计数按计数降序排列。

这是我目前拥有的工作解决方案,我正在寻求帮助转换为单个Linq查询。

Module Module1

Class Tag
    Property Name As String
    Property Count As Integer
End Class

Class Product
    Property Name As String
    Property tags As List(Of Tag)
End Class

Sub Main()

    Dim Products As New List(Of Product) From {
            {New Product With {.Name = "P1",
                               .tags = New List(Of Tag) From {{New Tag With {.Name = "T1"}},
                                                              {New Tag With {.Name = "T3"}},
                                                              {New Tag With {.Name = "T5"}}
                                                             }
                              }
            },
            {New Product With {.Name = "P2",
                               .tags = New List(Of Tag) From {{New Tag With {.Name = "T2"}},
                                                              {New Tag With {.Name = "T4"}},
                                                              {New Tag With {.Name = "T6"}}
                                                             }
                              }
            },
            {New Product With {.Name = "P3",
                               .tags = New List(Of Tag) From {{New Tag With {.Name = "T2"}},
                                                              {New Tag With {.Name = "T3"}},
                                                              {New Tag With {.Name = "T4"}}
                                                             }
                              }
            },
            {New Product With {.Name = "P4",
                               .tags = New List(Of Tag) From {{New Tag With {.Name = "T4"}},
                                                              {New Tag With {.Name = "T5"}},
                                                              {New Tag With {.Name = "T6"}},
                                                              {New Tag With {.Name = "T7"}},
                                                              {New Tag With {.Name = "T8"}}
                                                             }
                              }
            }
        }


    Dim ReportingTags As New List(Of Tag)

    '-- Start : Needs to be converted to pure Linq (if possible)------------------------------------------

    Dim InterimTags As New List(Of String)

    For Each p As Product In Products
        Dim TmpTags As New List(Of String)
        InterimTags.AddRange(TmpTags.Concat(From t In p.tags Select t.Name))
    Next

    ReportingTags.AddRange((From t In InterimTags
                            Group By name = t Into Count = Count()
                            Select New Tag With {.Name = name,
                                                 .Count = Count}).OrderByDescending(Function(t) t.Count))

    '-- End ----------------------------------------------------------------------------------------------

    For Each t As Tag In ReportingTags
        Console.WriteLine("Tag: {0} - Count: {1}", t.Name, t.Count)
    Next

    Console.ReadLine()

End Sub

结束模块

我将获取输出并将其转换为observablecollection(TagModel) - 所以我试图消除数据的双重/三重处理。

由于

格雷姆

1 个答案:

答案 0 :(得分:0)

我是C#家伙,但Linq是Linq,所以我想我会被刺伤。我可以通过在红色部分中添加以下内容来匹配您的结果:

Dim outStuff = From t In Products.SelectMany(Function(p) p.tags)
               Group By tagName = t.Name
               Into g = Group, Count()
               Order By Count Descending

然后我用

For Each t In outStuff
    Console.WriteLine("Tag: {0} - Count: {1}", t.tagName, t.Count)
Next

进行输出。

我确定这不是最优雅或优雅的VB,你可以将Linq改进得更漂亮一点,但对你来说这应该是一个好的开始。

您问题中的示例代码帮助我们完成了很多工作。

如需快速解释,如果您不熟悉SelectMany或Group By,他们会做一些不同且非常有用的事情。

SelectMany的工作方式与Select类似,不同之处在于,当应用于集合属性时,所有集合属性的内容将被展平并作为相应类型的单个集合返回,而不是作为集合集合返回。在这种情况下,它从所有产品中获取所有标签,并将它们放入一个集合中进行处理。

Group By做了相反的事情,并采用了一个大的扁平组,并将其转换为集合的集合,根据指定的标准(在这种情况下为t.Name)进行分组。