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

时间:2016-11-17 15:23:22

标签: c# linq generic-list

我尝试使用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; }
}

当我合并这两个列表时,新列表并不包含&#34; innerLinks&#34; FirstLink和SecondLink的记录。 我尝试了以下代码:

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

现在,FirstLink将获得按&#34; TableId&#34;分组的所有表格,但只有少数&#34; innerLinks&#34;来自SecondLink的遗失。

我需要&#34; innerLinks&#34;来自新合并列表中的FirstLink和SecondLink,无需重复。

示例:

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]

2 个答案:

答案 0 :(得分:1)

这是一个选项:

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

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

假设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的innerLinks上使用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<T>解释了on MSDN
覆盖EqualsGetHashCode on MSDN

答案 1 :(得分:1)

您的查询不起作用,因为在进行分组时,您正在使用该组的第一个元素,并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();