Как оптимизировать этот запрос LINQ для объектов? - PullRequest
1 голос
/ 23 января 2012

Я сопоставляю некоторые объекты в списках памяти с запросом .contains (subselect), чтобы отфильтровать старых от новых пользователей.

Проверка на проблемы с производительностью я видел это:

enter image description here

В oldList в основном входят около 1000 пользователей, а новый список варьируется от 100 до 500. Есть ли способ оптимизировать этот запрос?

Ответы [ 3 ]

3 голосов
/ 23 января 2012

Абсолютно - строить набор вместо проверки списка каждый раз:

// Change string to whatever the type of UserID is.
var oldUserSet = new HashSet<string>(oldList.Select(o => o.UserID));
var newUsers = NewList.Where(n => !oldUserSet.Contains(n.UserID))
                      .ToList();

Проверка сдерживания для HashSet должна быть O (1), предполагая несколько коллизий хешей, вместо O (N) проверки каждого на всю последовательность (для каждого нового пользователя).

2 голосов
/ 23 января 2012

Вы можете заранее сделать HashSet<T> своих идентификаторов пользователя. Это приведет к тому, что Contains станет операцией O (1):

var oldSet = new HashSet<int>(oldList.Select(o => o.UserID));
var newUsers = NewList.Where(n => !oldSet.Contains(n.UserID)).ToList();
0 голосов
/ 23 января 2012

Хотя эти HashSet<T> ответы просты и просты, некоторые могут предпочесть решение, ориентированное на linq.

LinqToObjects реализует объединение и GroupJoin с помощью HashSet.Просто используйте один из них - в этом примере используется GroupJoin:

List<User> newUsers =
  (
    from n in NewList
    join o in oldList on n.UserId equals o.UserId into oldGroup
    where !oldGroup.Any()
    select n
  ).ToList()
...