4

I have two lists:

List<string> _list1;
List<string> _list2;

I need add all _list2 different items on _list1...

How can I do that using LINQ?

Thanks

Robaticus
  • 22,857
  • 5
  • 54
  • 63
Paul
  • 12,359
  • 20
  • 64
  • 101

3 Answers3

10

You would use the IEnumerable<T>.Union method:

var _list1 = new List<string>(new[] { "one", "two", "three", "four" });
var _list2 = new List<string>(new[] { "three", "four", "five" });

_list1 = _list1.Union(_list2);

// _distinctItems now contains one, two, three, four, five

EDIT

You could also use the method the other post uses:

_list1.AddRange(_list2.Where(i => !_list1.Contains(i));

Both of these methods are going to have added overhead.

The first method uses a new List to store the Union results (and then assigns those back to _list1).

The second method is going to create an in-memory representation of Where and then add those to the original List.

Pick your poison. Union makes the code a bit clearer in my opinion (and thus worth the added overhead, at least until you can prove that it is becoming an issue).

Justin Niessner
  • 242,243
  • 40
  • 408
  • 536
  • This creates a new list; it doesn't add anything to _list1. – Gabe Aug 11 '10 at 18:48
  • @Carlos - Any specific reason to not use this? – Justin Niessner Aug 11 '10 at 18:54
  • Well in this particular example it's fine. But if the Collection has some sort of state like some ORM lists of objects they could fail when updating to the DB since the collection that has all the DB-related information is the one that was lost when assining the new one. – Carlos Muñoz Aug 11 '10 at 18:58
  • @Carlos - Either of the methods describe here are going to rely on Equals. Both Union and Contains allow you to supply your own IComparer to use instead of relying on Equals. You're right about the ORM issue though. If you're working with ORM managed Lists (that handle Inserts, etc.), then AddRange would be the option that more correctly defines your intent. – Justin Niessner Aug 11 '10 at 19:01
  • @Justin: Yes my mistake, I edited my comment. I have suffered already when merging two lists that is why I remember this case – Carlos Muñoz Aug 11 '10 at 19:02
  • 1
    +1 I like simplicity with Union but I believe AddRange(list2.Except(..)) is faster than your second approach (See comment on Carlos' answer). Union is properly a little bit slower than AddRange(list2.Except(..)) because you create a new List but asymptotically it should be the same I guess. – Lasse Espeholt Aug 11 '10 at 19:20
10
// Add all items from list2 except those already in list1
list1.AddRange(list2.Except(list1));
Lee
  • 142,018
  • 20
  • 234
  • 287
5
_list1.AddRange( _list2.Where(x => !_list1.Contains(x) ) );
Carlos Muñoz
  • 17,397
  • 7
  • 55
  • 80
  • 1
    Won't this run in O(n^2)? Ideally it should not be slower than sorting which is O(n*log(n)) for comparison-sorts. – Lasse Espeholt Aug 11 '10 at 19:01
  • @lasseespeholt You can't be sure if the Lists are sorted. – Carlos Muñoz Aug 11 '10 at 19:06
  • @Carlos That is not what I'm saying. I'm saying that I think the performance of your expression is O(n*m) where n is list1.Length and m is list2.Length. And it should not be slower than sorting which can be done in O(n*log n) because if you are concatenating the lists and sorts then you can remove duplicates in O(n) time so it will be O(n*log n). – Lasse Espeholt Aug 11 '10 at 19:11
  • http://stackoverflow.com/questions/2799427 This states that Union is O(n) which is A LOT faster than that. – Lasse Espeholt Aug 11 '10 at 19:15
  • @lasseespeholt Why does it have to be not slower than sorting? I didn't see it as a requirement. Also since you have two unsorted lists there is no other way (i can think of) of finding out which of the elements in the second list are in the first other than searching secuentially. And you have to do this for all items of second list so it has to be O(n^2). – Carlos Muñoz Aug 11 '10 at 19:21
  • @Carlos - You could add the items in the first list into a `HashSet` and then test for membership of each item in the second - this approach is linear in the length of the longer list. This is why using Union and Except are more efficient. – Lee Aug 11 '10 at 19:35
  • @Carlos I meant there is a solution which is at least as fast as sorting. Union, Except and Distinct is O(n). It ain't a requirement but Paul should at least know this solution is slow. And furthermore is it longer than the faster solution. This is not some personal hetz and I haven't down-voted because this is indeed a correct answer. But again, this is not a optimal nor pretty solution and therefore have I up-voted, in my head, better solutions. Regards... – Lasse Espeholt Aug 11 '10 at 19:41
  • I also have upvoted the other solution which apperead I think after mine so I have no problem with that – Carlos Muñoz Aug 11 '10 at 20:10