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)進行分組。