如何在 C# 中合并两个列表并合并其内部列表而不重复

How to Merge two lists and Merge it's inner lists without duplication in C#

我正在尝试使用 LINQ 合并两个通用列表-

List<LinkedTable> FirstLink
List<LinkedTable> SecondLink

如下图Class所示,我的通用列表本身就有一个通用列表。

public class LinkedTable
{
    public string TableId { get; set; }
    public string TableName { get; set; }
    public List<Link> innerLinks { get; set; }
}

public class Link
{
    public Boolean linkFlag;
    public string Descriptor { get; set; }
    public string RecordId { get; set; }
}

当我合并两个列表时,新列表不包含 FirstLink 和 SecondLink 的 "innerLinks" 记录。 我试过以下代码:

FirstLink = FirstLink.Concat(SecondLink)
                     .GroupBy(e1 => e1.TableId)
                     .Select(e2 => e2.FirstOrDefault())
                     .ToList();

现在,FirstLink 将获得按 "TableId " 分组的所有表格,但缺少 SecondLink 中的一些 "innerLinks"。

我需要新合并列表中 FirstLink 和 SecondLink 的 "innerLinks" 列表,不重复。

示例:

FirstLink[0].innerLinks[0]
            .innerLinks[1]
            .innerLinks[2]

SecondLink[0].innerLinks[1]
             .innerLinks[2]
             .innerLinks[3]

合并Link应该是:

FirstLink[0].innerLinks[0]
            .innerLinks[1]
            .innerLinks[2]            
            .innerLinks[3]

这里有一个选项:

首先,您必须提供一种方法来告诉 Linq 什么使 Link 等于另一个。您可以通过以下任一方法执行此操作:

  • 创建一个 class 工具 IEqualityComparer<Link> 并将其实例作为参数传递给 Distinct
  • 在 Link class
  • 上实施 IEquatable<Link> 并覆盖 GetHashCode
  • 覆盖 EqualsGetHashCode Link class。

假设 RecordId 是 Link 对象的唯一标识符,这就是实现 IEquatable<Link>:

的方法
public class Link : IEquatable<Link>
{
    public Boolean linkFlag;
    public string Descriptor { get; set; }
    public string RecordId { get; set; }

    public bool Equals(Link other)
    {
        //Adjust for a suiting identifier and do all the sanity checks, if needed.
        return this.RecordId == other.RecordId;
    }

    public override int GetHashCode()
    {
        //You can also use another GetHash approach that suits you better.
        return this.RecordId.GetHashCode();
    }
}

然后,您可以 Concat 两个列表,然后按 TableId 和 TableName 分组。最后,您在分组的 LinkedTable 的内部 Link 上使用 SelectMany 到 select 该组中包含的所有 Link。 Distinct 将必须采用 IEqualityComparer 的实例,以防您选择那样做。

var merged = 
    from item in FirstLink.Concat(SecondLink)
    group item by new { Id = item.TableId, Name = item.TableName } into tbGp
    select new LinkedTable
    {
        TableId = tbGp.Key.Id,
        TableName = tbGp.Key.Name,
        innerLinks = tbGp.SelectMany(p => p.innerLinks).Distinct().ToList()
    };

DistinctIEquatable<T> 解释 on MSDN
覆盖 EqualsGetHashCode on MSDN

您的查询不起作用,因为当您分组时,您正在获取组的第一个元素和它的 Link 个对象列表

要实现您的结果,您应该尝试以下代码:

var FirstLink = FirstLink
    .Concat(SecondLink)
    .GroupBy(e1 => e1.TableId)
    // Don't take the first item, but create a new one with the items you need
    .Select(e2 => new LinkedTable
        {
            TableId = e2.Key,
            TableName = e2.First().TableName,
            innerLinks = e2.SelectMany(x => x.innerLinks).ToList()
        })
    .ToList();