2016-11-17 6 views
1

Я пытаюсь объединить два общий список с помощью LINQ-Как объединить два списка и объединить его внутренние списки без дублирования в C#

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

Когда я объединить два списка, новый список не содержит оба «innerLinks» записи FirstLink и SecondLink. Я попытался следующий код:

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

Теперь FirstLink получит все таблицы, сгруппированные по «TABLEID», но несколько «innerLinks» из SecondLink отсутствует.

Мне нужен список «innerLinks» от FirstLink и SecondLink в новом объединенном списке без повторения.

Пример:

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

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

Merged Ссылка должна быть:

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

вы пробовали что-то вроде 'Еогеаспа (вар пункта в SecondLink) {FirstLink.Add (пункт);}' – Sam07

+0

Возможного дубликат [Как для объединения двух списков с использованием LINQ?] (http://stackoverflow.com/questions/4872943/how-to-merge-two-lists-using-linq) –

ответ

1

Вот вариант:

Во-первых, вы должны будете предоставить способ сказать Linq, что делает ссылку равным другому. Вы можете сделать это с помощью любого из этих методов:

  • создания класса орудия IEqualityComparer<Link> и передать его экземпляр в качестве параметра Distinct;
  • реализации IEquatable<Link> и первостепенную GetHashCode на классе Link
  • переопределяя Equals и GetHashCode на классе Link.

Предполагая, что 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. Наконец, вы используете SelectMany на сгруппированных внутренних ссылках LinkedTable, чтобы выбрать все ссылки, содержащиеся в этой группе. 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() 
    }; 

Distinct и IEquatable<T> объяснил on MSDN
Переопределение Equals и GetHashCodeon MSDN

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();