Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Using Linq query inside List<T>.AddRange to conditionally add elements from one list to another

Tags:

c#

linq

I have a List<String> and two List<CustomObject>.
I want to combine two List<CustomObject> but only if second List<CustomObject> property is not contained in List<String>.

So, want to do something like this:

resultSet1.AddRange(resultSet2.Select(x => !names.Contains(x.City)).ToList());

What am I missing here?

like image 944
inutan Avatar asked Oct 19 '11 15:10

inutan


1 Answers

You are misusing Select when you should be using Where.

resultSet1.AddRange(resultSet2.Where(x => !names.Contains(x.City));

Select is a projection method. It takes a sequence and selects it, sometimes selecting the entire item, a single property, or projecting it into something else entirely.

Where is a filtering method. It takes a sequence and applies a predicate to it, yielding only the elements that pass the predicate.

(In your example, by using Select, you're effectively trying to add a list of bool to a list of CustomObject, which is not going to work.)


Not addressing the specific error at hand, here are some additional ideas to consider.

This is a situation where a HashSet<string> might be beneficial for names, particularly if names is significantly large. Contains on a HashSet<T> is of O(1) complexity, whereas it is O(n) for List<T>. However, there is overhead associated with the HashSet, so if you have any concerns, it's best to measure both and see which is more performant.

One more thing that might help, if you simply need to stream one sequence after the other and do not necessarily need to change or add to either collection, you might consider using Union or Concat operations.

var sequence = resultSet1.Union(resultSet2.Where(x => !names.Contains(x.City)));
var sequence = resultSet1.Concat(resultSet2.Where(x => !names.Contains(x.City)));

The difference in the two being that Union will filter out any duplicates in the resulting sequence (from both inputs, not just the second against the first), Concat applies no duplicate-filtering logic and simply streams one sequence after the other. The input sequences (resultSet1 and resultSet2) are unmodified.

like image 165
Anthony Pegram Avatar answered Sep 23 '22 12:09

Anthony Pegram