基本上,我有一个产品列表和一个搜索选项。当搜索多个单词时,我想返回任何包含按任何顺序搜索的所有单词的产品。
因此,如果用户搜索"绿色衬衫",则返回的列表将包括"绿色T恤大"," T恤绿色媒体"等我的(坏)代码:
public List<Products> FindProductsByName(string query, int limit)
{
string[] words = query.ToLower().Split(' ');
List<Products> products = new List<Products>();
foreach (var word in words)
{
products.AddRange(All.Where(x => x.ProductName.ToLower().Contains(word)).Take(limit).ToList());
//this will return all products which contains ANY word in the searched word list
}
return products;
}
所以基本上,我想要
All.Where(x => x.Productname.ToLower().Contains(words[0]) && x.Productname.ToLower().Contains(words[1]) ...
但我不知道搜索查询中会有多少单词。我觉得这应该很容易,但我的大脑并非如此。今天工作。我错过了什么?
答案 0 :(得分:4)
我认为您正在寻找Linq方法Intersect()
。
dotnetfiddle上的工作示例。
代码:
public static void Main()
{
var list = FindProductsByName("green shirt", 2);
foreach (var products in list)
Console.WriteLine(products.ProductName);
}
public static IEnumerable<Products> FindProductsByName(string query, int limit)
{
string[] words = query.ToLower().Split(' ');
List<Products> products = new List<Products>
{
new Products { ProductName = "green t-shirt large" },
new Products { ProductName = "t-shirt green medium" },
new Products { ProductName = "t-shirt red" }
};
return
(from p in products
let productsComponent = p.ProductName.Split(' ') // you should make a list of keyword in Products instead
where productsComponent.Intersect(words).Any()
select p).Take(limit);
}
public class Products
{
public string ProductName { get; set; }
}
输出
green t-shirt large
t-shirt green medium
编辑:我忘了添加limit
。所以我加了它。
答案 1 :(得分:2)
在aloisdg发布他出色的解决方案之前,我能够提出一个有效的解决方案。这是我的工作代码:
string[] words = query.ToLower().Split(' ');
var products = from p in All select p;
foreach (var word in words)
{
products = products.Where(x => x.ProductName.ToLower().Contains(word));
}
return products.Take(limit).ToList();
我想避免将产品名称分解为字符串数组并使用intersect命令,因为表中有大约30,000个产品,这会减慢速度。
感谢大家的帮助。
答案 2 :(得分:0)
您可以使用LINQ方法All
products.Where(p=> words.All(w=> p.ProductName.Contains(w));
我拿了aloisdg dotnetfiddle并更新了我的答案。