LINQ возвращает элементы в списке, которые соответствуют любым именам (строка) в другом списке - PullRequest
31 голосов
/ 28 марта 2011

У меня есть 2 списка. 1 - это коллекция продуктов. А другой - это набор товаров в магазине.

Мне нужно иметь возможность вернуть все shopProducts, если имена совпадают с какими-либо именами в продуктах.

У меня есть это, но это не похоже на работу. Есть идеи?

    var products = shopProducts.Where(p => p.Name.Any(listOfProducts.
             Select(l => l.Name).ToList())).ToList();

Мне нужно сказать, дайте мне все шоппродукты, где есть имя в другом списке.

Ответы [ 5 ]

66 голосов
/ 28 марта 2011
var products = shopProducts.Where(p => listOfProducts.Any(l => p.Name == l.Name))
                           .ToList();

Для LINQ-to-Objects, если listOfProducts содержит много элементов, то может получить лучшую производительность, если вы создадите HashSet<T>, содержащий все необходимые имена, а затем используете его в своемзапрос.HashSet<T> имеет производительность поиска O (1) по сравнению с O (n) для произвольного IEnumerable<T>.

var names = new HashSet<string>(listOfProducts.Select(p => p.Name));
var products = shopProducts.Where(p => names.Contains(p.Name))
                           .ToList();

Для LINQ-to-SQL я ожидал (надеюсь?), Что провайдер можетоптимизировать сгенерированный SQL автоматически без необходимости ручной настройки запроса.

10 голосов
/ 28 марта 2011

Вы можете использовать объединение, например:

var q = from sp in shopProducts
        join p in listOfProducts on sp.Name equals p.Name
        select sp;

Более полное руководство по объединению: здесь .

4 голосов
/ 28 марта 2011

Вы можете создать IEqualityComparer<T>, который говорит, что продукты с одинаковыми именами равны.

class ProductNameEqulity : IEqualityComparer<Product>
{
    public bool Equals(Product p1, Product p2)
    {
        return p1.Name == p2.Name
    }

    public int GetHashCode(Product product)
    {
        return product.Name.GetHashCode();
    }
}

Затем вы можете использовать это в методе расширения Intersect.

var products = shopProducts.Intersect(listOfProducts, new ProductNameEquality());
2 голосов
/ 28 марта 2011
var products = shopProducts
        .Where(shopProduct =>
                listOfProducts.Any(p => shopProduct.Name == p.Name))
        .ToList();
2 голосов
/ 28 марта 2011

Попробуйте, пожалуйста

var products  = shopProducts.Where(m=> listOfProducts.Select(l=>l.Name).ToList().Contains(m=>m.Name));
...