LINQ返回一个列表中与另一个列表中任何名称(字符串)匹配的项目。

35

我有2个列表。一个是产品的集合,另一个是商店里的产品集合。

如果名称与“产品”中的任何名称匹配,我需要能够返回所有“商店产品”。

我有以下代码,但它似乎无法工作。有什么想法吗?

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

我需要获取所有在另一个列表中存在名称的商店产品。


感谢大家的评论!我现在已经让它工作了...再次感谢。答案已被接受。 - Martin
5个回答

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

对于LINQ-to-Objects,如果listOfProducts包含许多项,则创建一个包含所需名称的HashSet<T>并在查询中使用它可能会获得更好的性能。HashSet<T>具有O(1)的查找性能,而对于任意的IEnumerable<T>,则为O(n)。

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

对于LINQ-to-SQL,我期望(希望?)提供程序可以自动优化生成的SQL,而无需手动调整查询。


谢谢。这真的很有帮助。 - ajexpress

10

你可以使用 JOIN,例如:

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

关于 join 的更全面指南请参见此处


我讨厌“特殊”的linq语法,但从概念上讲,使用linq-to-sql可能是正确的选择。对于linq to object,我不确定哪种方法会更有效。 - mavnn
关于linq-to-object - 这个答案中的查询最终会转换为一个Enumerable.Join调用,根据文档,它具有哈希查找。http://msdn.microsoft.com/en-us/library/bb534675.aspx - “默认的相等比较器Default用于哈希和比较键。” - devgeezer

4
您可以创建一个 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());

3
请试一下这个。
var products  = shopProducts.Where(m=> listOfProducts.Select(l=>l.Name).ToList().Contains(m=>m.Name));

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

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接