Reputation: 45
I have a list of object ids that I would like to retrieve from another list of object that every object has his own unique id.
List<string> idList
List<ObjectWithId> objectList
class ObjectWithId
{
string Id;
...
}
I know how to do it one by one. But is it possible to do it in one line using LINQ?
Upvotes: 1
Views: 1247
Reputation: 5812
There are a number of ways you could do this, but you need to be careful if performance is a consideration.
For example, in addition to a simple Where
, you could use the Join
operator as follows to find the matching objects:
var objects = Enumerable.Range(0, 1000)
.Select(a => new ObjectWithId() { Id = a.ToString() })
.ToList();
var ids = Enumerable
.Range(0, 1000 / 2).Select(a => a.ToString())
.ToList();
var matchedObjects = objects.Join(
inner: ids,
outerKeySelector: a => a.Id,
innerKeySelector: a => a,
resultSelector: (objectWithId, id) => objectWithId)
.ToList();
If I contrast the performance of the above with the .Where
operator:
objects.Where(m => ids.Contains(m.Id)).ToList();
On my computer I see this:
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| Method | N | Mean | Error | StdDev | Rank |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| LinqJoin | 10 | 997.5 ns | 18.938 ns | 17.714 ns | 2 |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| LinqWhere | 10 | 793.2 ns | 9.905 ns | 8.271 ns | 1 |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| LinqJoin | 1000 | 103,635.0 ns | 1,049.670 ns | 930.505 ns | 3 |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| LinqWhere | 1000 | 2,873,539.1 ns | 49,073.330 ns | 45,903.223 ns | 5 |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| LinqJoin | 10000 | 1,002,157.5 ns | 12,564.510 ns | 11,138.111 ns | 4 |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
| LinqWhere | 10000 | 283,998,696.5 ns | 4,953,233.368 ns | 4,633,257.566 ns | 6 |
+--------------+-----------+--------------------+-------------------+-------------------+-------+
In otherwords, .Where
outperforms .Join
when there are 10 objects, marginally. By the time we get to 1000 objects, .Join
is outperforming it by a factor of nearly 28 - and at 10,000, by a factor of more than 280.
This is because Join
will create an index in advance of all the keys from the object and in the list it is being joined for, internally probably using a hash. This means as it iterates the outer list, a simple lookup to this index can be done to locate a match. However, with the .Where
and .Contains
approach, this is essentially a nested list, with worst case O(N^2) complexity. It can only compete when there are a small numbers of items in the list, because .Join
has the overhead of creating the index.
Upvotes: 2
Reputation: 353
use this:
objectList.Where(m=> idList.Contains(m.Id)).ToList();
Upvotes: 7