Shittu Joseph Olugbenga
Shittu Joseph Olugbenga

Reputation: 6476

Combining two Lists of an Object into one

I am currently developing an application that requires this senario.

Assuming I have this object

public class ObjectItem
{
   public int Id {get;set;}
   public int Name {get;set;}
   public int Sex {get;set;}
   public int Age {get;set;}
   public string Complexion {get;set;}
}

If we now have two lists of this object

var studentWithAge = new List<ObjectItem>
                  {
                    new ObjectItem {Id = 1, Name = "John", Age = 2},
                    new ObjectItem {Id = 2, Name = "Smith", Age = 5},
                    new ObjectItem {Id = 3, Name = "Juliet", Age = 7},
                  };

var studentWithSexAndComplexion = new List<ObjectItem>
                       {
                          new ObjectItem {Id = 1, Name = "John", Sex = "Male", Complexion = "fair"},
                          new ObjectItem {Id = 2, Name = "Smith", Sex = "Male", Complexion = " "},
                          new ObjectItem {Id = 3, Name = "Juliet", Sex = "Female", Complexion = "Blonde"},
                          new ObjectItem {Id = 4, Name = "Shittu", Sex = "Male", Complexion = "fair"},
                       };

I want to merge these two lists into just one. The end result should look like this.

var CompleteStudentData=new List<ObjectItem>
{
   new ObjectItem{Id=1,Name="John",Sex="Male", Complexion="fair",Age=2},
   new ObjectItem{Id=2,Name="Smith",Sex="Male", Complexion=" ", Age=5},
   new ObjectItem{Id=3,Name="Juliet",Sex="Female", Complexion="Blonde", Age=7},
   new ObjectItem{Id=4,Name="Shittu",Sex="Male", Complexion="fair", Age=0},
}

How do i achieve this? Using Union to merge the two list does not produce the desired result. I would appreciate your help.

Upvotes: 2

Views: 1850

Answers (3)

Jeff Mercado
Jeff Mercado

Reputation: 134811

Since it's possible that your collections will not have a 1-to-1 correspondence, you would have to do a full outer join. See here for how you can compose it that way.

Here's one way you can get similar results.

Collect all the keys (the ids) from both collections, then perform a left join with each of the collections, then combine the results.

var ids = studentWithAge.Select(s => s.Id)
    .Union(studentWithSexAndComplexion.Select(s => s.Id));
var query =
    from id in ids
    from sa in studentWithAge
                    .Where(sa => sa.Id == id)
                    .DefaultIfEmpty(new ObjectItem { Id = id })
    from ssc in studentWithSexAndComplexion
                    .Where(ssc => ssc.Id == id)
                    .DefaultIfEmpty(new ObjectItem { Id = id })
    select new ObjectItem
    {
        Id = id,
        Name = sa.Name ?? ssc.Name,
        Sex = ssc.Sex,
        Age = sa.Age,
        Complexion = ssc.Complexion,
    };

Upvotes: 1

StepUp
StepUp

Reputation: 38094

.Net has a function which is concatenating collections:

var concatenatedCollection = StudentWithAge.Concat(StudentWithSexAndComplexion).ToList();

        var StudentWithAge = new List<ObjectItem>()
        {
            new ObjectItem{Id=1,Name="John",Age=2},
            new ObjectItem{Id=2,Name="Smith",Age=5},
            new ObjectItem{Id=3,Name="Juliet",Age=7},   
        };

        var StudentWithSexAndComplexion = new List<ObjectItem>()
        {
            new ObjectItem{Id=1,Name="John",Sex="Male", Complexion="fair"},
            new ObjectItem{Id=2,Name="Smith",Sex="Male", Complexion=" "},
            new ObjectItem{Id=3,Name="Juliet",Sex="Female", Complexion="Blonde"},
            new ObjectItem{Id=4,Name="Shittu",Sex="Male", Complexion="fair"},
        };
        var concatenatedCollection = StudentWithAge.Concat(StudentWithSexAndComplexion).ToList();

Upvotes: -1

aush
aush

Reputation: 2108

var result = StudentWithAge.Join(StudentWithSexAndComplexion, 
                                 sa => sa.Id,
                                 ssc => ssc.Id,
                                 (sa, ssc) => new ObjectItem
                                 {
                                    Id = sa.Id,
                                    Name = sa.Name, 
                                    Age = sa.Age, 
                                    Sex = ssc.Sex, 
                                    Complexion = ssc.Complexion
                                 }).ToList();

Or, avoiding creation of new objects:

var result = StudentWithAge.Join(StudentWithSexAndComplexion, 
                                 sa => sa.Id,
                                 ssc => ssc.Id,
                                 (sa, ssc) => 
                                 { 
                                    sa.Sex = ssc.Sex; 
                                    sa.Complexion = ssc.Complexion; 
                                    return sa;
                                 }).ToList();

And if you want to add students presented only in the second list, than also:

result.AddRange(StudentWithSexAndComplexion.Where(ssc => !StudentWithAge.Any(sa => sa.Id == ssc.Id)));

Upvotes: 4

Related Questions