检查字符串是否包含任何顺序的字符串列表
Check if string contains a list of strings in any order
基本上,我有一个产品列表和一个搜索选项。当搜索多个词时,我想 return 包含以任何顺序搜索的所有词的任何产品。
因此,如果用户搜索 "green shirt",returned 列表将包括 "green t-shirt large"、"t-shirt green medium" 等。我的(错误)代码:
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]) ...
但我不知道搜索查询中会有多少词。我觉得这应该很容易,但我的大脑今天不工作。我错过了什么?
我认为您正在寻找 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
。所以我加了它。
在 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 命令,因为 table 中有约 30,000 种产品,这会减慢速度。
谢谢大家的帮助。
您可以使用 LINQ 方法 All
products.Where(p=> words.All(w=> p.ProductName.Contains(w));
我使用了 aloisdg dotnetfiddle 并更新了我的答案。
基本上,我有一个产品列表和一个搜索选项。当搜索多个词时,我想 return 包含以任何顺序搜索的所有词的任何产品。
因此,如果用户搜索 "green shirt",returned 列表将包括 "green t-shirt large"、"t-shirt green medium" 等。我的(错误)代码:
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]) ...
但我不知道搜索查询中会有多少词。我觉得这应该很容易,但我的大脑今天不工作。我错过了什么?
我认为您正在寻找 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
。所以我加了它。
在 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 命令,因为 table 中有约 30,000 种产品,这会减慢速度。
谢谢大家的帮助。
您可以使用 LINQ 方法 All
products.Where(p=> words.All(w=> p.ProductName.Contains(w));
我使用了 aloisdg dotnetfiddle 并更新了我的答案。