比较和合并对象列表

3

我有一个包含许多对象的列表,其定义如下:

Public Class Helper
    Public Property UserPrincipal As UserPrincipal
    Public Property Groups As New List(Of String)
    Public Property Server As New List(Of String)
End Class

假设有一个对象长这样:

UserPrincipal.Name = Jan
Groups = {group_1, group_2, group_3}
Server = {Server1}

还有一个:

UserPrincipal.Name = Jan
Groups = {group_1, group_3}
Server = {Server2}

现在,我想检查每个对象的属性“Groups”,如果一个对象的“Groups”包含另一个对象的“Groups”,则创建一个新对象。

因此,新的对象列表应该像这样:

UserPrincipal.Name = Jan
Groups = {group_1, group_2, group_3}
Server = {Server1, Server2}

这是否可以使用linq来实现?
谢谢和问候, Jan
更新:10:42:将'Server'属性的类型从字符串更改为列表(of字符串)
更新12:04:让我试着澄清我的问题。 任务是收集服务器本地组的成员。为此,我使用具有正确凭据的新principalcontext连接到每个服务器,获取正确的组(它是远程桌面用户组),并获取此组的所有成员。 有了这些信息,我填充了提到的“helper”对象,其中包含userprincipal(它是该组的成员)、组(它们是远程桌面用户组的成员)和服务器名称。
因此,我得到n * Helper对象,其中n是服务器计数。
现在,有两个要求:假设我在这里有两个服务器,server1和server2。一切都相等,但服务器名称不同,因此我只想要一个属性为Server = {server1,server2}的对象。
第二个要求基本上与第一个相同,但是:如果Groups属性至少包含一个唯一相关项,并且如果它尚未包含在其中,则将此组添加到列表中。
不知道现在是否更清楚了:)现在将展示一个简短的示例。
对象1: UserPrincipal.Name = Jan Groups = {Domain-Users} Server = {Server1}
对象2: UserPrincipal.Name = Jan Groups = {Domain-Users} Server = {Server2}
预期对象: UserPrincipal.Name = Jan Groups = {Domain-Users} Server = {Server1,Server2}
示例2: 对象1: UserPrincipal.Name = Jan Groups = {Domain-Users,Test-Users} Server = {Server1}
对象2: UserPrincipal.Name = Jan Groups = {Test-Users} Server = {Server2}
预期对象: UserPrincipal.Name = Jan Groups = {Domain-Users,Test-Users} Server = {Server1,Server2}
最后一个,呼: 对象1: UserPrincpial.Name = Jan Groups = {Test-Users} Server = {Server1}
对象2: UserPrincipal.Name = Jan Groups = {Domain-Users} Server = {Server1}或{Server2}等无所谓。
预期结果:没有更改,因为属性组完全不同。

您不能将属性“Server”的类型从字符串更改为“List(Of string)”。因此,您必须在第一次使用列表或使用字符串并使用逗号(或其他分隔符)连接所有内容。 - Tim Schmelter
你可以这样做,但不能使用Option Strict On。但请注意,这不是推荐的做法。 - lsteinme
UserPrincipal 是如何相关的?同一组也有相同的 UserPrincipal 吗?或者你想保留哪个组,第一个? - Tim Schmelter
“UserPrincipal”并不直接关联到组,但通常它是组的成员。但由于我在这里没有使用“GroupPrincipal”的列表,所以这并不重要。 - Jan
在您的示例数据中,似乎GroupsServer属性只是针对每个UserPrincipal进行联合。但是,您的描述听起来像是某种交集。您能否请澄清一下? - Enigmativity
@Jan:我之所以问是因为否则我只能取每个组的任意“UserPrincipal”。请看我的下面的答案,特别是x.group.First().UserPrincipal。你没有提到规则,所以我使用了“First”。 - Tim Schmelter
1个回答

0
根据您更新的问题和评论,这似乎是您想要的内容:
Dim upGroups = From helper In helpers 
               Group helper By helper.UserPrincipal Into Group
               Select New Helper With {
                 .UserPrincipal = UserPrincipal,
                 .Groups = Group.SelectMany(Function(h) h.Groups).Distinct().ToList(),
                 .Server = Group.SelectMany(Function(h) h.Server).Distinct().ToList()
               }
Dim newHelpers = upGroups.ToList()

旧答案

您可以使用Groups.Intersect(h.Groups).Any()来检查哪些帮助程序包含相交的组。然后,您可以使用循环将它们合并:

Dim query = From helper In helpers
            Let group = helpers.Where(Function(h) helper.Groups.Intersect(h.Groups).Any())

Dim processed As New HashSet(Of Helper)()
Dim newHelpers As New List(Of Helper)
For Each x In query
    If x.group.Any(AddressOf processed.Contains) Then
        ' was already processed, skip '
        Continue For
    End If
    Dim mergedHelper = New Helper With {
               .UserPrincipal = x.group.First().UserPrincipal,
               .Groups = x.group.SelectMany(Function(h) h.Groups).Distinct().ToList(),
               .Server = x.group.SelectMany(Function(h) h.Server).Distinct().ToList()
           }
    newHelpers.Add(mergedHelper)
    For Each helperInGroup In x.group
        processed.Add(helperInGroup)
    Next
Next

似乎某处出现了错误。它只输出了大约5个条目,而我的初始helperlist包含将近20.000个条目。 :) - Jan
我正在接近您的方法。我只是没有使用您处理过的哈希集。然而,现在我得到了每个服务器相同的结果集,而不仅仅是一个。使用您的代码,我只得到一个用户主体,而不是全部。 - Jan
@Jan:不,它们并没有消失,而只有每个组的第一个被拿走了。如果你看一下我对你问题的评论,早些时候我已经告诉过你了。仍然不清楚你想如何合并它们。此外,我还没有实现你的新需求(你所谓的“第一个要求”),即将具有相同组但不同服务器的助手也分组。目前,我只是将相交组的助手分组,无论它们有什么服务器。 - Tim Schmelter
@Jan:你想要什么限制,如果在组中没有匹配项,你希望使用相同的userprincipal创建一个新对象?恐怕我不明白“创建新”意味着什么。你是想创建一个副本还是将这个单一的userprincipal添加进去? - Tim Schmelter
@Jan:但是您没有为每个用户主体组设置重复的服务器,对吗?Distinct()函数可以去除重复项。 - Tim Schmelter
显示剩余9条评论

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接