Using a Linq query inside a <T> .AddRange list to conditionally add items from one list to another
I have a List<String>
and two List<CustomObject>
.
I want to combine two List<CustomObject>
, but only if the second property List<CustomObject>
not contained in List<String>
.
So you want to do something like this:
resultSet1.AddRange(resultSet2.Select(x => !names.Contains(x.City)).ToList());
What am I missing here?
You abuse Select
when you should use Where
.
resultSet1.AddRange(resultSet2.Where(x => !names.Contains(x.City));
Select
is the projection method. He takes a sequence and selects it, sometimes selects the whole element, one property, or projects it onto something else.
Where
is a filtering method. It takes a sequence and applies a predicate to it, giving only those elements that convey the predicate.
(In your example, using Select
, you are actually trying to add the bool
list to the CustomObject
list, which will not work.)
Without addressing a specific error, we will consider some additional ideas.
This is a situation where a HashSet<string>
may be useful for names
, especially if names
significantly large. Contains
on a HashSet<T>
has complexity O (1), while O (n) for List<T>
. However, there is overhead associated with HashSet, so if you have any problems, it is best to measure them and see which is more efficient.
Another thing that can help if you just need to pass one sequence after another and do not have to change or add to any collection, you can use Union
or Concat
.
var sequence = resultSet1.Union(resultSet2.Where(x => !names.Contains(x.City))); var sequence = resultSet1.Concat(resultSet2.Where(x => !names.Contains(x.City)));
The difference is that Union
will filter out any duplicates in the resulting sequence (from both inputs, not just the second to the first), Concat
does not apply the filter duplication logic and simply passes one sequence after the other. Input sequences ( resultSet1
and resultSet2
) are unmodified.