8

I have an object which has a date and a list of people, a person has a first and last name. Something like:

PeopleInfo
----------
DateTime - StartDate
List<Person> - People

Person
------
string - FirstName
string - LastName

I have a list of people info where there are multiple StartDates the same each with its own list of people. Is it possible to merge these into a single object using linq?

Example

StartDate - 1/1/2011, People Bob, Sue, Jane
StartDate - 2/2/2011, People Scott, Rob, Mark
StartDate - 1/1/2011, People Fred, Gill, Jack

Expected output

StartDate - 1/1/2011, People Bob, Sue, Jane, Fred, Gill, Jack
StartDate - 2/2/2011, People Scott, Rob, Mark

Is this possible in linq?

Thanks

2 Answers 2

8

You could do:

List<PeopleInfo> peopleInfos = ...

var merged = from peopleInfo in peopleInfos
             group peopleInfo by peopleInfo.StartDate into dateGroup
             select new PeopleInfo
             {
                 StartDate = dateGroup.Key,
                 People = dateGroup.SelectMany(pi => pi.People)
                                   .Distinct()
                                   .ToList()
             };

But this really looks like a hack; I would recommend you design the container class in a way that prevents this 'duplicate date' scenario from occurring in the first place. e.g. an implementation of ILookup<DateTime, Person> or IDictionary<DateTime, List<Person>> or a HashSet<PeopleInfo> that uses StartDate for equality.

Sign up to request clarification or add additional context in comments.

2 Comments

Thanks that works great. A better implementation is a good idea but what I'm doing is just a hack for the time being anyway.
I would agree the OP model leaves something to be desired, but your solution is spot on!
1
ILookup<DateTime, Person> lookup =
  (
    from pi in PeopleInfos
    from person in pi.People
    select new {StartDate = pi.StartDate, Person = person }
  ).ToLookup(x => x.StartDate, x => x.Person);

OR

List<PeopleInfo> list =
  (
    from pi in PeopleInfos
    from person in pi.People
    group person by pi.StartDate into g
    select new PeopleInfo() { StartDate = g.Key, People = g.ToList() }
  ).ToList()

2 Comments

+1. I would warn that while this is correct, it unnecessarily flattens the whole input collection and does the grouping from scratch.
Unnecessary flattening? What does it cost?

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.