Reputation: 2681
I've got the following class
public class Application
{
public int Id { get; set; }
public int Version { get; set; }
(...)
}
And I have the following IEnumerable<Application>
:
IEnumerable<Application> applications1 = new List<Application>
{
new Application {Id = 1, Version = 1},
new Application {Id = 2, Version = 1},
new Application {Id = 3, Version = 3}
};
IEnumerable<Application> applications2 = new List<Application>
{
new Application {Id = 1, Version = 2},
new Application {Id = 3, Version = 2}
new Application {Id = 4, Version = 1}
};
How can I merge them into a single IEnumerable<Application>
using LINQ while ensuring that if two Applications
have the same Id
only the one with the highest Version
is added to the new IEnumerable<Application>
, effectively my final `IEnumerable should be equivalent to:
IEnumerable<Application> final = new List<Application>
{
new Application {Id = 1, Version = 2},
new Application {Id = 2, Version = 1},
new Application {Id = 3, Version = 3},
new Application {Id = 4, Version = 1}
}
Upvotes: 4
Views: 2888
Reputation: 23298
Why just don't write something like that?
var result = applications1
.Concat(applications2).GroupBy(x => x.Id)
.Select(g => new Application { Id = g.Key, Version = g.Max(a => a.Version) });
You concatenate both collections, group items by Id
, then select new Application
instance with group key as an Id
and max Version
.
If you don't want to create a new Application
instance, the following code might help, by looking a max Version
for every group and return an Application
with max Version
value
var result = applications1
.Concat(applications2).GroupBy(x => x.Id)
.Select(g =>
{
var maxVersion = g.Max(a => a.Version);
return g.First(a => a.Version == maxVersion);
});
Upvotes: 1
Reputation: 143453
You can use GroupBy
combined with selecting maximum in group via Aggregate
:
IEnumerable<Application> final = applications1
.Concat(applications2)
.GroupBy(a => a.Id)
.Select(g => g.Aggregate((acc, curr) => acc.Version > curr.Version ? acc: curr))
.ToList();
Upvotes: 5
Reputation: 57996
A more procedural way would be:
var concat = applications1.Concat(applications2)
.ToArray();
var final = concat
.GroupBy(a => a.Id)
.Select (g => new
{
ApplicationId = g.Key,
MaxVersion = g.Max(i => i.Version)
})
.Select(i => concat.FirstOrDefault(
existing => existing.Id == i.ApplicationId &&
existing.Version == i.MaxVersion))
.ToList();
Upvotes: 1