1

我试图编写一个可以从父级产品的外部集合中连接内部标签集合的单个Linq查询,并返回标签集合一个统一的计数命令按计数递减。Linq从外部集合的内部集合中列出具有count的标签列表

这里有一个工作的解决方案,我目前有和正在寻求帮助转换为单个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 

前端模块

我将采取输出,并将其转换为(的TagModel)一个的ObservableCollection - 所以我试图消除数据的双/三处理。

感谢

格雷姆

回答

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)进行分组。