Ответ Даррена Коппа :
var excluded = items1.Except(items2);
- лучшее решение с точки зрения производительности.
(NB: Это верно, по крайней мере, для обычного LINQ, возможно, LINQ to SQL меняет положение вещей согласно посту Марко Руссо . Однако я думаю, что в «худшем случае» Даррен Метод Коппа будет возвращать, по крайней мере, скорость метода Руссо даже в среде LINQ to SQL).
В качестве быстрого примера попробуйте это в LINQPad :
void Main()
{
Random rand = new Random();
int n = 100000;
var randomSeq = Enumerable.Repeat(0, n).Select(i => rand.Next());
var randomFilter = Enumerable.Repeat(0, n).Select(i => rand.Next());
/* Method 1: Bramha Ghosh's/Marco Russo's method */
(from el1 in randomSeq where !(from el2 in randomFilter select el2).Contains(el1) select el1).Dump("Result");
/* Method 2: Darren Kopp's method */
randomSeq.Except(randomFilter).Dump("Result");
}
Попробуйте прокомментировать один из двух методов одновременно и попробуйте производительность для разных значений n.
Мой опыт (на моем ноутбуке Core 2 Duo), кажется, подсказывает:
n = 100. Method 1 takes about 0.05 seconds, Method 2 takes about 0.05 seconds
n = 1,000. Method 1 takes about 0.6 seconds, Method 2 takes about 0.4 seconds
n = 10,000. Method 1 takes about 2.5 seconds, Method 2 takes about 0.425 seconds
n = 100,000. Method 1 takes about 20 seconds, Method 2 takes about 0.45 seconds
n = 1,000,000. Method 1 takes about 3 minutes 25 seconds, Method 2 takes about 1.3 seconds
Метод 2 (ответ Даррена Коппа) явно быстрее.
Снижение скорости для метода 2 для больших n, скорее всего, связано с созданием случайных данных (не стесняйтесь добавлять разность в DateTime, чтобы подтвердить это), тогда как метод 1 явно имеет проблемы алгоритмической сложности (и просто глядя на вас можно видеть, что это по крайней мере O (N ^ 2), поскольку для каждого числа в первом наборе он сравнивается со всем вторым сбором).
Вывод: Используйте ответ Даррена Коппа о методе LINQ 'Except'