VB.NET LINQ-将分层数据与平面数据匹配

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} -

我有两个来自两个不同系统的相似数据的表示,我需要将一个系统中的每个实体与另一个系统中的实体相匹配

系统A是分层的,表示为
字典(字符串、列表(类别))
看起来像:

- "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
to
CategoryB.Org
)和类别名称(
CategoryB.name
to
CategoryB.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