4

I have two classes which share two common attributes, Id and Information.

public class Foo
{
     public Guid Id { get; set; }

     public string Information { get; set; }

     ...
}
public class Bar
{
     public Guid Id { get; set; }

     public string Information { get; set; }

     ...
}

Using LINQ, how can I take a populated list of Foo objects and a populated list of Bar objects:

var list1 = new List<Foo>();
var list2 = new List<Bar>();

and merge the Id and Information of each into a single dictionary:

var finalList = new Dictionary<Guid, string>();

Thank you in advance.

Jonathan
  • 13,947
  • 17
  • 94
  • 123
  • What do you want to have happen if there are two items with the same ID but different information? – Erik Philips Jul 25 '12 at 17:46
  • @ErikPhilips This eventuality will not occur, so it's not something I need to handle. – Jonathan Jul 25 '12 at 17:46
  • Check here for solution: http://stackoverflow.com/questions/4038978/map-two-lists-into-a-dictionary-in-c-sharp – Mitja Bonca Jul 25 '12 at 17:48
  • Since you have common attributes does it make sense that they should be inheriting from base class or since they are properties implementing an interface? – Brad Semrad Jul 25 '12 at 17:49

2 Answers2

8

Sounds like you could do:

// Project both lists (lazily) to a common anonymous type
var anon1 = list1.Select(foo => new { foo.Id, foo.Information });
var anon2 = list2.Select(bar => new { bar.Id, bar.Information });

var map = anon1.Concat(anon2).ToDictionary(x => x.Id, x => x.Information);

(You could do all of this in one statement, but I think it's clearer this way.)

Jon Skeet
  • 1,421,763
  • 867
  • 9,128
  • 9,194
0
   var finalList = list1.ToDictionary(x => x.Id, y => y.Information)
            .Union(list2.ToDictionary(x => x.Id, y => y.Information))
                        .ToDictionary(x => x.Key, y => y.Value);

Make sure the ID's are unique. If not they will be overwritten by the first dictionary.

EDIT: added .ToDictionary(x => x.Key, y => y.Value);

The Internet
  • 7,959
  • 10
  • 54
  • 89
  • 2
    Yes, it will work - but it seems a little wasteful, IMO. Why build three dictionaries *and* go via a set operation when you can just concatenate and use a single ToDictionary call? – Jon Skeet Jul 25 '12 at 18:06
  • I guess I don't know how much more expensive it is to create two anonymous lists over two dictionaries, or the performance benefits of .Conact() over .Union() *waves white flag* – The Internet Jul 25 '12 at 18:25
  • In terms of *memory*, my approach is the winner IMO. It doesn't need to build *any* intermediate collections. `Concat` is blindingly simple compared with `Union` which has to build a set for "already returned" values. The two extra `ToDictionary` calls will also require a bunch of hashing and potentially equality checks. Using a tuple-like value type (e.g. `KeyValuePair`) directly instead of using an anonymous type would potentially be slightly cheaper still, but uglier. I think my version also wins in terms of *simplicity* - you don't logically want to build those intermediate dictionaries. – Jon Skeet Jul 25 '12 at 18:32