Каков «современный» способ найти общие элементы в двух списках <T>объектов? - PullRequest
10 голосов
/ 26 июля 2011

У меня есть два универсальных списка, содержащих разные типы, например, давайте назовем их Products и Employees. Я пытаюсь найти продукты, расположенные в том же месте, что и сотрудники, т. Е. Где product.SiteId == emp.SiteId

List<Product> lstProds;
List<Employees> lstEmps;

Мой мозг (старый skool) говорит мне использовать forEach цикл для поиска совпадений, но я подозреваю, что есть («лучше» / терсер / быстрее?) Способ сделать это с помощью Linq. Кто-нибудь может осветить меня? Все примеры, которые я нашел в Интернете, имеют дело со списками примитивов (строк / целых) и не особенно полезны.

1 Ответ

17 голосов
/ 26 июля 2011

Я бы сказал:

var products = from product in lstProds
               join employee in lstEmps on product.SiteId equals employee.SiteId
               select product;

Однако, если есть несколько сотрудников с одинаковым идентификатором сайта, вы получите продукты несколько раз. Вы можете использовать Distinct, чтобы исправить это, или создать набор идентификаторов сайта:

var siteIds = new HashSet<int>(lstEmps.Select(emp => emp.SiteId));

var products = lstProds.Where(product => siteIds.Contains(product.SiteId));

Это предполагает, что SiteId - это int - если это анонимный тип или что-то подобное, вам может потребоваться дополнительный метод расширения:

public static HashSet<T> ToHashSet<T>(this IEnumerable<T> source)
{
    return new HashSet<T>(source);
}

Тогда:

var siteIds = lstEmps.Select(emp => emp.SiteId).ToHashSet();
var products = lstProds.Where(product => siteIds.Contains(product.SiteId));

В качестве альтернативы, если у вас мало сотрудников, это будет работать, но относительно медленно:

var products = lstProds.Where(p => lstEmps.Any(emp => p.SiteId == emp.SiteId));

Добавьте вызов ToList к любому из этих подходов, чтобы получить List<Product> вместо IEnumerable<Product>.

...