【问题标题】:How to Merge two lists and Merge it's inner lists without duplication in C#如何在 C# 中合并两个列表并合并它的内部列表而不重复
【发布时间】:2016-11-17 15:23:21
【问题描述】:

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

List<LinkedTable> FirstLink
List<LinkedTable> SecondLink

如下面的类所示,我的泛型列表本身就有一个泛型列表。

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]

合并的链接应该是:

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

【问题讨论】:

标签: c# linq generic-list


【解决方案1】:

这里有一个选项:

首先,您必须提供一种方法来告诉 Linq 是什么让一个链接与另一个链接相等。您可以通过以下任何一种方法做到这一点:

  • 创建一个实现IEqualityComparer&lt;Link&gt;的类并将其实例作为参数传递给Distinct
  • 在 Link 类上实现 IEquatable&lt;Link&gt; 并覆盖 GetHashCode
  • 覆盖链接类上的EqualsGetHashCode

假设 RecordId 是 Link 对象的唯一标识符,这就是您通过实现 IEquatable&lt;Link&gt; 的方法:

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 的内部链接上使用 SelectMany 来选择该组中包含的所有链接。 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&lt;T&gt; 解释on MSDN
覆盖EqualsGetHashCode on MSDN

【讨论】:

    【解决方案2】:

    您的查询不起作用,因为当您进行分组时,您正在获取 Group 的第一个元素及其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();
    

    【讨论】:

      猜你喜欢
      • 2013-09-08
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-10-06
      • 2016-01-17
      • 2021-02-11
      • 2017-06-05
      • 2014-08-30
      相关资源
      最近更新 更多