Reputation: 21
I'm trying to merge two generic list using LINQ-
List<LinkedTable> FirstLink
List<LinkedTable> SecondLink
As shown in the Class below, my generic list itself has a generic list in it.
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; }
}
When I merge the two lists, the new list doesn't contain both the "innerLinks" records of FirstLink and SecondLink. I have tried the following code:
FirstLink = FirstLink.Concat(SecondLink)
.GroupBy(e1 => e1.TableId)
.Select(e2 => e2.FirstOrDefault())
.ToList();
Now FirstLink will get all the Tables grouped by "TableId ", but a few "innerLinks" from SecondLink is missing.
I need both the list of "innerLinks" from FirstLink and SecondLink in the new merged List without repetition.
Example:
FirstLink[0].innerLinks[0]
.innerLinks[1]
.innerLinks[2]
SecondLink[0].innerLinks[1]
.innerLinks[2]
.innerLinks[3]
Merged Link should be:
FirstLink[0].innerLinks[0]
.innerLinks[1]
.innerLinks[2]
.innerLinks[3]
Upvotes: 1
Views: 1271
Reputation: 1743
Here's an option:
First, you'll have to provide a way to tell Linq what makes a Link equal to another. You can do this by any of this methods:
IEqualityComparer<Link>
and pass an instance of it as parameter to Distinct
; IEquatable<Link>
and overriding GetHashCode
on the Link classEquals
and GetHashCode
on the Link class. Assuming that RecordId is the unique identifier for a Link object, this is how you do it by implementing 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();
}
}
Then, you can Concat
both lists, then group by TableId and TableName. Last, you use SelectMany
on the grouped LinkedTable's innerLinks to select all Links contained on that group. The Distinct
will have to take an instance of the IEqualityComparer
in case you opted to go that way.
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
and IEquatable<T>
explained on MSDN
Overriding Equals
and GetHashCode
on MSDN
Upvotes: 1
Reputation: 3154
Your query doesn't work because when you are grouping you are taking the first element of the Group and its list of Link
objects.
To achieve your result you should try the following code:
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();
Upvotes: 1