VB.NET LINQ-将分层数据与平面数据匹配
我有两个来自两个不同系统的相似数据的表示,我需要将一个系统中的每个实体与另一个系统中的实体相匹配 系统A是分层的,表示为VB.NET LINQ-将分层数据与平面数据匹配,vb.net,linq,Vb.net,Linq,我有两个来自两个不同系统的相似数据的表示,我需要将一个系统中的每个实体与另一个系统中的实体相匹配 系统A是分层的,表示为字典(字符串、列表(类别))看起来像: - "Organization 1" - { Name = "Cat1", Id = 1} - { Name = "Cat2", Id = 2} - { Name = "Cat3", Id = 3} - "Organization 2" - { Name = "Cat1", Id = 4} -
字典(字符串、列表(类别))
看起来像:
- "Organization 1"
- { Name = "Cat1", Id = 1}
- { Name = "Cat2", Id = 2}
- { Name = "Cat3", Id = 3}
- "Organization 2"
- { Name = "Cat1", Id = 4}
- { Name = "Cat3", Id = 5}
- { Name = "Cat4", Id = 6}
- "Organization 3"
- { Name = "Cat1", Id = 7}
- { Name = "Cat2", Id = 8}
- { Name = "Cat3", Id = 9}
- { Name = "Cat4", Id = 10}
- "Organization 1"
- { Name = "Cat1", Id = 1}, { Org = "Organization 1", Name = "Cat1", Id = 100 }
- { Name = "Cat2", Id = 2}, { Org = "Organization 1", Name = "Cat2", Id = 101 }
- { Name = "Cat3", Id = 3}, { Org = "Organization 1", Name = "Cat3", Id = 102 }
- "Organization 2"
- { Name = "Cat1", Id = 4}, { Org = "Organization 2", Name = "Cat1", Id = 103 }
- { Name = "Cat3", Id = 5}, null
- { Name = "Cat4", Id = 6}, { Org = "Organization 2", Name = "Cat4", Id = 105 }
- "Organization 3"
- { Name = "Cat1", Id = 7}, null
- { Name = "Cat2", Id = 8}, null
- { Name = "Cat3", Id = 9}, null
- { Name = "Cat4", Id = 10}, null
系统B被展平,表示为(类别B的)列表
- { Org = "Organization 1", Name = "Cat1", Id = 100 }
- { Org = "Organization 1", Name = "Cat2", Id = 101 }
- { Org = "Organization 1", Name = "Cat3", Id = 102 }
- { Org = "Organization 2", Name = "Cat1", Id = 103 }
- { Org = "Organization 2", Name = "Cat2", Id = 104 }
- { Org = "Organization 2", Name = "Cat4", Id = 105 }
- { Org = "Organization 4", Name = "Cat1", Id = 106 }
- { Org = "Organization 4", Name = "Cat2", Id = 107 }
- { Org = "Organization 4", Name = "Cat3", Id = 108 }
- { Org = "Organization 4", Name = "Cat4", Id = 109 }
基本上,我需要做的是将层次结构数据与组织名称(Dictionary.Key
toCategoryB.Org
)和类别名称(CategoryB.name
toCategoryB.name
)上的扁平化数据进行外部连接,这样我就有了一个字典(字符串,IEnumerable(元组,CategoryB)))
或类似于:
- "Organization 1"
- { Name = "Cat1", Id = 1}
- { Name = "Cat2", Id = 2}
- { Name = "Cat3", Id = 3}
- "Organization 2"
- { Name = "Cat1", Id = 4}
- { Name = "Cat3", Id = 5}
- { Name = "Cat4", Id = 6}
- "Organization 3"
- { Name = "Cat1", Id = 7}
- { Name = "Cat2", Id = 8}
- { Name = "Cat3", Id = 9}
- { Name = "Cat4", Id = 10}
- "Organization 1"
- { Name = "Cat1", Id = 1}, { Org = "Organization 1", Name = "Cat1", Id = 100 }
- { Name = "Cat2", Id = 2}, { Org = "Organization 1", Name = "Cat2", Id = 101 }
- { Name = "Cat3", Id = 3}, { Org = "Organization 1", Name = "Cat3", Id = 102 }
- "Organization 2"
- { Name = "Cat1", Id = 4}, { Org = "Organization 2", Name = "Cat1", Id = 103 }
- { Name = "Cat3", Id = 5}, null
- { Name = "Cat4", Id = 6}, { Org = "Organization 2", Name = "Cat4", Id = 105 }
- "Organization 3"
- { Name = "Cat1", Id = 7}, null
- { Name = "Cat2", Id = 8}, null
- { Name = "Cat3", Id = 9}, null
- { Name = "Cat4", Id = 10}, null
我没有权限访问类别
对象,无法将组织属性应用于该对象,否则我会这样做,并让自己更轻松。我只是不知道如何连接字典键和它的值中某个项的属性,最终得到任何有用的东西。我创建的最成功的实现包括首先为每个循环创建一个,然后在其中创建一个LINQ查询:
Given:
catA = Dictionary(Of String, List(Of CategoryA))
catB = List(Of CategoryB)
Dim result As New Dictionary(Of String, List(Of Tuple(Of CategoryA, CategoryB)))
For Each kvp As KeyValuePair(Of String, List(Of CategoryA)) In catA
Dim orgName As String = kvp.Key
If Not result.ContainsKey(orgName) Then
result.Add(orgName, New List(Of Tuple(Of CategoryA, CategoryB)))
End If
Dim orgCategories As IEnumerable(Of CategoryB) =
From cat In catB Where cat.Org = orgName
Dim tmpResult As IEnumerable(Of Tuple(Of CategoryA, CategoryB)) =
From cat_a In kvp.Value
Group Join cat_b In orgCategories
On cat_a.Name Equals cat_b.Name
Into matchedCats = Group
From cat In matchedCats.DefaultIfEmpty
Select matches = Tuple.Create(cat_a, cat)
result(orgName).AddRange(tmpResult)
Next
它工作正常,但我希望它是在相同的声明。好吧,这有点工作,但我坚持你的for循环
Public Class CategoryA
Public Property Name As String
Public Property Id As Integer
End Class
Public Class CategoryB
Public Property Org As String
Public Property Name As String
Public Property Id As Integer
End Class
Private SystemA As New Dictionary(Of String, List(Of CategoryA))
Private SystemB As New List(Of CategoryB)
Sub Main()
SystemA.Add("Org1", New List(Of CategoryA) From {New CategoryA() With {.Id = 1, .Name = "Cat1"},
New CategoryA() With {.Id = 2, .Name = "Cat2"},
New CategoryA() With {.Id = 3, .Name = "Cat3"}})
SystemA.Add("Org2", New List(Of CategoryA) From {New CategoryA() With {.Id = 4, .Name = "Cat1"},
New CategoryA() With {.Id = 5, .Name = "Cat2"},
New CategoryA() With {.Id = 6, .Name = "Cat3"}})
SystemA.Add("Org3", New List(Of CategoryA) From {New CategoryA() With {.Id = 7, .Name = "Cat1"},
New CategoryA() With {.Id = 8, .Name = "Cat2"},
New CategoryA() With {.Id = 9, .Name = "Cat3"},
New CategoryA() With {.Id = 10, .Name = "Cat4"}})
SystemB.Add(New CategoryB() With {.Org = "Org1", .Name = "Cat1", .Id = 100})
SystemB.Add(New CategoryB() With {.Org = "Org1", .Name = "Cat2", .Id = 101})
SystemB.Add(New CategoryB() With {.Org = "Org1", .Name = "Cat3", .Id = 102})
SystemB.Add(New CategoryB() With {.Org = "Org2", .Name = "Cat1", .Id = 103})
SystemB.Add(New CategoryB() With {.Org = "Org2", .Name = "Cat2", .Id = 104})
SystemB.Add(New CategoryB() With {.Org = "Org2", .Name = "Cat4", .Id = 105})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat1", .Id = 106})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat2", .Id = 107})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat3", .Id = 108})
SystemB.Add(New CategoryB() With {.Org = "Org4", .Name = "Cat4", .Id = 109})
Dim AllOrgs = SystemA.Keys.Union(SystemB.Select(Function(b) b.Org).Distinct)
Dim BothCats2 = From org In AllOrgs
Let CatAList = If(Not SystemA.ContainsKey(org), New List(Of CategoryA), From cat In SystemA(org))
Let CatBList = (From cat In SystemB Where cat.Org = org).ToList
Let AllCatNames = (From cat In CatAList Select cat.Name Distinct).Union(From cat In CatBList Select cat.Name Distinct)
Let BothCats = (From cat In AllCatNames
From A In CatAList.Where(Function(CatA) CatA.Name = cat).DefaultIfEmpty
From B In CatBList.Where(Function(CatB) CatB.Name = cat).DefaultIfEmpty)
Select org, BothCats
End Sub