2

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.

2
  • AddRange() Commented Feb 28, 2015 at 16:23
  • 1
    This looks like an outer join. Commented Feb 28, 2015 at 16:25

3 Answers 3

4
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)));
Sign up to request clarification or add additional context in comments.

1 Comment

Due to the nature of the ObjectItem and the contents of the two lists, could be better to join by Name and not Id.
1

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,
    };

4 Comments

This answer perfectly solves my problem. So i have marked this has the correct answer.
I've made a slight adjustment to the query, the left join in query syntax is needlessly complex. I've replaced it with an equivalent query.
@frenchie: I tried your answer, but it left out the 'ObjectItem' with ID=4 from the list. That's the reason i did not accept it as the right asnwer. However, I appreciate your help.
Ah yes, didn't see the lists were of different sizes!
-1

.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();

Comments

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.