2013-06-03 103 views
2

在vb.net中,使用linq,連接2個對象列表。 這兩個列表都是相同的類型。vb.net linq對象列表

我搜索最好的方式來連接兩個列表按ID分組。 就像一個獨特的。

樣品:

Imports System.Text 
Imports System.Reflection 

Module Module1 

    Sub Main() 
     Dim list1 As New List(Of Item) 
     For i As Integer = 1 To 4 
      list1.Add(New Item(i, i.ToString)) 
     Next 

     Dim list2 As New List(Of Item) 
     For i As Integer = 3 To 6 
      list2.Add(New Item(i, i.ToString)) 
     Next 

     Dim list3 As New List(Of Item) 
     list3 = (list1.Concat(list2)).ToList 
     Console.WriteLine(Item.PrintList(list3).ToString)   

     Console.ReadLine() 
    End Sub 

End Module 

Class Item 
    Private _Id As Integer 
    Private _Value As String 

    Public Property Id() As Integer 
     Get 
      Return _Id 
     End Get 
     Set(ByVal value As Integer) 
      _Id = value 
     End Set 
    End Property 
    Public Property Value() As String 
     Get 
      Return _Value 
     End Get 
     Set(ByVal value As String) 
      _Value = value 
     End Set 
    End Property 

    Public Sub New() 
    End Sub 
    Public Sub New(ByVal id As Integer, ByVal value As String) 
     Me.Id = id 
     Me.Value = value 
    End Sub 

    Public Overrides Function ToString() As String 
     Dim sb = New Text.StringBuilder()   
     For Each item In [GetType]().GetFields(BindingFlags.NonPublic Or BindingFlags.Instance) 
      sb.Append(String.Format("[{0} = {1}] ", item.Name, item.GetValue(Me))) 
     Next 
     Return sb.ToString() 
    End Function 

    Public Shared Function PrintList(ByVal myList As List(Of Item)) As StringBuilder 
     Dim result As New StringBuilder 
     For Each i In myList 
      result.AppendLine(i.ToString) 
     Next 
     Return result 
    End Function 

End Class 

什麼項目list3 CONCAT後包含:

[_Id = 1] [_Value = 1] 
[_Id = 2] [_Value = 2] 
[_Id = 3] [_Value = 3] 
[_Id = 4] [_Value = 4] 
[_Id = 3] [_Value = 3] 
[_Id = 4] [_Value = 4] 
[_Id = 5] [_Value = 5] 
[_Id = 6] [_Value = 6] 

我們所希望的:

[_Id = 1] [_Value = 1] 
[_Id = 2] [_Value = 2] 
[_Id = 3] [_Value = 3] 
[_Id = 4] [_Value = 4] 
[_Id = 5] [_Value = 5] 
[_Id = 6] [_Value = 6] 

回答

4

我搜到Concat的兩個列表分組的最佳方法由Id。像 不同。

使用Enumerable.Union

但是,您需要首先在Item類中覆蓋EqualsGetHashCode。然後,所有的LINQ方法將使用您的ID:

Class Item 
    Public Property ID As Int32 

    Public Overrides Function Equals(obj As Object) As Boolean 
     If obj Is Nothing Then Return False 
     If Not TypeOf obj Is Item Then Return False 
     Return Id = DirectCast(obj, Item).Id 
    End Function 

    Public Overrides Function GetHashCode() As Integer 
     Return Id.GetHashCode() 
    End Function 
End Class 

現在你可以使用Union這是高效而明確:

Dim list3 = list1.Union(list2).ToList 

MSDN

這種方法排除複製從返回集。這與Concat<TSource>方法的行爲不同 行爲,該方法返回輸入序列中包括重複項的所有 元素。 ...要比較一個自定義數據類型 ,您需要實現此接口並提供您自己的GetHashCode等於方法的類型。

+0

爲誰想知道爲什麼GetHashCode:http://stackoverflow.com/questions/371328/why-is-it-important-to-override-gethashcode-when-equals-method-is-overridden – forX

+0

斯蒂芬是正確的太。 Concat Distinct是聯盟的替代品。 – forX

+0

@forX:'GetHashCode'就像'Equals'的預過濾器。每個使用散列碼查找對象的散列表(例如'Dictionary','HashSet')將首先使用'GetHashCode',然後確認與'Equals'相等。 'GetHashCode'必須高效。對於兩個不同的對象,'GetHashCode'可能返回相同的數字,但每個相同的對象必須具有相同的哈希碼。這些規則和準則非常有用:http://blogs.msdn.com/b/ericlippert/archive/2011/02/28/guidelines-and-rules-for-gethashcode.aspx –

1

通過添加添Schmelter答案的Equals和GetHashCode的,你現在還可以選擇使用的毗連和.Distinct直接在查詢的可能性:

Dim list3 As List(Of Item) = list1.Concat(list2).Distinct.ToList 

或使用地點和查詢不同:

Dim list3 As List(Of Item) = (From data In list1.Concat(list2) Where data.Value = "MyCity" Distinct).ToList 

變化:

Dim list3 As List(Of Item) = (From data In list1.Concat(list2) Where data.Value = "MyCity").Distinct.ToList