LINQ zwraca pozycje na liście, które pasują do dowolnych nazw (string) na innej liście

Mam 2 listy. 1 to kolekcja produktów. A drugi to kolekcja produktów w sklepie.

Muszę być w stanie zwrócić wszystkie produkty, jeśli nazwy pasują do nazw produktów.

Mam to, ale nie działa. Jakieś pomysły?
    var products = shopProducts.Where(p => p.Name.Any(listOfProducts.
             Select(l => l.Name).ToList())).ToList();

Muszę powiedzieć, że daj mi wszystkie produkty, gdzie nazwa istnieje na drugiej liście.

Author: halfer, 2011-03-28

5 answers

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

Dla LINQ-to-Objects, jeśli listOfProducts zawiera wiele elementów, to może uzyskać lepszą wydajność, jeśli utworzysz HashSet<T> zawierającą wszystkie wymagane nazwy i użyjesz jej w zapytaniu. HashSet<T> ma wydajność o(1) w porównaniu do O(n) dla dowolnego IEnumerable<T>.

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

Dla LINQ-to-SQL, oczekiwałbym (hope?), że dostawca może zoptymalizować wygenerowany SQL automatycznie bez konieczności ręcznego dostosowywania zapytania.

 64
Author: LukeH,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 09:09:25

Możesz użyć join, na przykład:

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

Pełniejszy przewodnik po join znajduje się tutaj .

 10
Author: Jon Egerton,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 08:53:07

Można utworzyć IEqualityComparer<T>, który mówi, że produkty o równych nazwach są równe.

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();
    }
}

Następnie możesz użyć tego w metodzie rozszerzenia Intersect.

var products = shopProducts.Intersect(listOfProducts, new ProductNameEquality());
 4
Author: Matt Ellen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 08:57:27

Spróbuj tego proszę

var products  = shopProducts.Where(m=> listOfProducts.Select(l=>l.Name).ToList().Contains(m=>m.Name));
 2
Author: Theun Arbeider,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 08:49:53
var products = shopProducts
        .Where(shopProduct =>
                listOfProducts.Any(p => shopProduct.Name == p.Name))
        .ToList();
 2
Author: mgronber,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2011-03-28 08:51:54