I have this class (simplified for easy reading)
public class Customer
{
public string Id {get;set;}
public Email[] Emails {get;set;}
}
From a external system I get a list with Customers
that can contain multiple lines for the same Customer
(ID)
Raw input JSON
[
{id: a1, emails:[a,b,c]},
{id: a1, emails:[d]},
{id: b3, emails:[e,f]},
{id: k77, emails:[z,a]}
]
c# code to fetch the Customers
List<Customer> dataInput = CallToExternalService(...);
I want to generate a unique list of Customers
via LINQ that contains a merged list of all the customers emails.
I know how to get a list of unique customers
dataInput.GroupBy(x => x.id).Select(x => x.First()).ToList();
But I'm struggling with how to merge the email lists into one for each customer. Also performance is an important factor since the data will contain 10k items and needs to run every hour.
I tried a lot, Select
and SelectMany
are good candidates but I cant wrap my head around how to merge lists, not to speak of taking this merged list back to the x.First()
item.
META CODE:
dataInput
.GroupBy(x => x.id)
.ForEachGroup(y => group.First().Emails = MergeLists(y.Emails;)
.Select(z => z.First()),ToList();
Expected End result C# List<>
id: a1, emails:[a,b,c,d]
id: b3, emails:[e,f]
id: k77, emails:[z,a]
CodePudding user response:
Making some assumptions about what you mean by "merge", but does this look right?
dataInput
.GroupBy(x => x.Id)
.Select(g=> new Customer
{
Id = g.Key,
Emails = g.SelectMany(c => c.Emails).ToArray()
})
.ToList();
CodePudding user response:
If you're sure that all the other properties are the same, you can use First
like in your initial attempt and modify @StriplingWarrior's answer like this:
dataInput
.GroupBy(x => x.Id)
.Select(g =>
{
var customer = g.First();
customer.Emails = g.SelectMany(c => c.Emails).ToArray();
return customer;
})
.ToList();
CodePudding user response:
If you're going to use Jack's approach, I'd suggest something slightly more robust.
var intermediate =
(
from g in dataInput.GroupBy(c => c.Id)
from c in g.Take(1)
select new
{
customer = c,
emails = g.SelectMany(d => d.Emails).ToArray()
}
)
.ToArray();
foreach (var x in intermediate)
{
x.customer.Emails = x.emails;
};
Customer[] ouput =
intermediate
.Select(x => x.customer)
.ToArray();