A: 

Using SQL on the database, the solution would be:

INSERT INTO List2 (ID)
SELECT      l1.ID
FROM        List1 l1
LEFT JOIN   List2 l2
        ON  l1.ID = l2.ID
WHERE       l2.ID IS NULL

Here the assumption is that the other columns in List2 table are either NOT NULL or have a DEFAULT value constraint.

van
The answer needs to be in LINQ not SQL, sorry.
Kane
If you need LINQ, then where is the problem?: You can get the results as you mentioned in the question. Then use those that for those that have no matches to create new objects (or add them to the lists)
van
Yeah, can't do it in SQL.
Svish
And that is exactly what I am asking about :P How would you do that cleanly and efficiently?
Svish
A: 
INSERT INTO List2(ID, Value)
SELECT      ID, 0
FROM        List1
WHERE       NOT EXISTS (SELECT NULL FROM List2 WHERE List2.ID=List1.ID)
richardtallent
Read other answers and their comments ...
tanascius
T-SQL is the most appropriate language, not LINQ.
richardtallent
Great ... but Svish tells us, that he can not use SQL ...
tanascius
I can't insert anything into the database. And I can't use SQL =/
Svish
+1  A: 

Assuming your lists are sorted by the Key value like in your example (in this case an integer), something like this should work:

int i = 0;

foreach (var item in List1)
{
    // Skip any items in List2 that don't exist in List1
    // (not sure this is needed in your case), or that we've
    // already passed in List1
    while (List2[i].Key < item.Key)
     i++;

    if (List2[i].Key > item.Key)
    {
     // Create new item in List2
     List2.Add(new List2Item(item.Key, 0));
    }
}

// TODO: resort List2

Depending on how many items you expect to be missing, you might want to Insert into List2 instead, eliminating the need for the resorting. If you expect a lot of items to be missing however, this method will be faster. Alternatively, you could use a linked list for List2.

Note that this will fail if there are duplicate Key entries in List1. You'd need to check for that seperately to prevent multiple new items from being created in List2.

Thorarin
A: 

LINQ: From the example you gave in the link, just change the code from:

foreach (var i in q) {
    Console.WriteLine("Customer: {0}  Order Number: {1}", 
        i.Name.PadRight(11, ' '), i.OrderNumber);
}

to

foreach (var i in q) {
    if (i.OrderNumber == "(no orders)")
        order.Add(new Order {Key = i.ID /* add your default values here*/});
}

Of course you can save some lines here as well in the code before.

van
A: 

OK, here is goes: 1. Create a type to represent an item from your lists:

 struct ListType
        {
            public object Id;
            public object Name;
        }

or, of course you can build in another way that suits you better.

  1. Create your List2 as an IEnumerable< ListType > from your LINQ query

  2. I assume List1 has the same structure as List2 with an Id and Name field (you could use the same ListType type for the list items)

  3. With the assumptions above, here is the code to solve the initial problem :

    List newLst2 = list2.ToList();

    Array.ForEach(list1.ToArray(), list1It =>
    {
       var isInList2 = from list2it in newLst2.ToArray()
                       where (string)list2it.Id == list1It.Id
                       select list2it;
    
    
       if (isInList2.Count() == 0)
           newLst2.Add(new ListType { Id = list1It.Id, Name = list1It.Name });
    
    
    });
    

Comments: for each element in List1 make a query in List2 and check if the Id exists. If it does not exist, add a new item.

There probably are more efficient ways of doing this but this should be able to get you started.

AlexDrenea
A: 

Here is a solution using LINQ.

public class List1
{
    public int ID { get; set; }
    public string Person { get; set; }
}

public class List2
{
    public int ID { get; set; }
    public int Value { get; set; }
}

var lList1 = new List<List1>
             {
                new List1 {ID = 1, Person = "Alice"},
                new List1 {ID = 2, Person = "Bob"},
                new List1 {ID = 3, Person = "Carol"},
                new List1 {ID = 4, Person = "Dave"}
             };


var lList2 = new List<List2>
             {
               new List2 {ID = 1, Value = 15},
               new List2 {ID = 1, Value = 19},
               new List2 {ID = 2, Value = 5},
               new List2 {ID = 2, Value = 7},
               new List2 {ID = 2, Value = 20},
               new List2 {ID = 4, Value = 16}
             };

var lOutput = lList1.SelectMany(pArg => 
                             lList2.Where(pArg1 => pArg1.ID == pArg.ID)
                                   .DefaultIfEmpty(new List2 { ID = pArg.ID, Value = 0})
                                   .Select(pArg1 => pArg1));
Vasu Balakrishnan
A: 

Uh... It seems like it would be straightforward to just use Contains, no?

foreach (Key key in List1.Keys)
{
   if (!List2.Keys.Contains(key)) List2.Add(key, "0");
}

This would have no issues with duplicate keys in List1.

genki
A: 

LINQ implementation

public class Master
{
    public int ID;
}

public class Detail
{
    public int ID;
    public int Count;
}

public static void AddMissingDetails(IEnumerable<Master> masters, List<Detail> details)
{
    AddMissingDetails(masters, details, x => new Detail
     {
      ID = x,
      Count = 0
     });
}

public static void AddMissingDetails(IEnumerable<Master> masters, List<Detail> details, Func<int, Detail> createDefault)
{
    details.AddRange(
     masters
      .Select(x => x.ID)
      .Except(details.Select(x => x.ID).Distinct())
      .Select(createDefault));
}
Handcraftsman
A: 

YOu may not like my solution. But i would like to thank you for this post. It gave me a chance to do some useful stuff using linq.

I am using Extension method and Linq to add the missing items in your target list (List2). I am not sure if you are working on 3.0/3.5 framework, if you do, then this solution would work for you and it is also "a clever, clean and efficient way of doing this" :).

 public static void MergeLists() {
      var listOne=new List<List1> {
        new List1 {ID=1, Person="Alice"},
        new List1 {ID=2, Person="Bob"},
        new List1 {ID=3, Person="Carol"},
        new List1 {ID=4, Person="Dave"},
        new List1 {ID=5, Person="Dave2"},
        new List1 {ID=6, Person="Dave3"},
      };
      var listTwo=new List<List2> {
        new List2 {ID=1, Value=15},
        new List2 {ID=1, Value=19},
        new List2 {ID=2, Value=5},
        new List2 {ID=2, Value=7},
        new List2 {ID=2, Value=20},
        new List2 {ID=4, Value=16}
      };

      var listTwoWithAddedItems=listOne.AddMissingItems(listTwo, (item1, item2) => item1.ID==item2.ID,
                                                    item2 => new List2 { ID=item2.ID, Value=-1 }).ToList();//For this value, you can put whatever default value you want to set for the missing items.

      Console.Read();
    }

     public static class AmbyExtends {

        public static List<Target> AddMissingItems<Source, Target>(this IEnumerable<Source> source, List<Target> target, Func<Source, Target, bool> selector, Func<Source, Target> creator) {
          foreach(var item in source) {
            if(!target.Any(x=>selector(item,x))) {
              target.Add(creator(item));
            }         
          }
          return target;
        }
      }
Amby
A: 
var lst1 = new List<int>() { 1, 2, 3, 4 };
var lst2 = new List<int>() { 1, 1, 2, 2, 2, 4 };

lst2.AddRange(lst1.Except(lst2));
JP Alioto