基于Linq的复杂搜索过滤器的构建
本文关键字:过滤器 构建 搜索 复杂 Linq 基于 | 更新日期: 2023-09-27 18:02:36
想知道是否有一个linq解决这个复杂的情况;例如,客户选择颜色:红色,尺寸:大号,类型:棉。如果我确信客户每次都会选择这些过滤器,我就会这样做:
var shirts = ListOfShirts.Where(i=> i.Color.Contains("red") && Size.Contains("Large") && Type.Contains("Cotton"));
下面是当前结构和一个动作方法,该方法接受来自视图的多个过滤器:
:
public partial class Shirt {
public long ID { get; set; }
public string Color { get; set; }
public string Size { get; set; }
public string Type { get; set; }
}
public class SelectedFilter {
public string Name { get; set; } // Filter Menu Title
public string Value { get; set; }
}
控制器:
public ActionResult Filter(IList<SelectedFilter> selectedFilters) {
var model = new List<Shirt>();
Shirt ListOfShirts = db.GetAllShirts();
var groups = selectedFilters.GroupBy(i => i.Name);
foreach (var g in groups)
{
var GroupName = g.FirstOrDefault().name;
var GroupValues = g.Select(i => i.value).ToList();
if (g.FirstOrDefault().name == "Color")
{
model = ListOfShirts.Where(i => GroupValues.Contains(i.Color)).ToList();
}
else if (g.FirstOrDefault().name == "Size")
{
model = ListOfShirts.Where(i => GroupValues.Contains(i.Size)).ToList();
}
else if (g.FirstOrDefault().name == "Type")
{
model = ListOfShirts.Where(i => GroupValues.Contains(i.Type)).ToList();
}
}
}
一种(残酷的)方法:
public ActionResult Filter(IList<SelectedFilter> selectedFilters) {
var model = new List<Shirt>();
IEnumerable<Shirt> ListOfShirts = db.GetAllShirts();
IEnumerable<Shirt> filteredListOfShirts = ListOfShirts
.Where(shirt => {
return (
(selectedFilters.Any(filter => filter.Name == "Color" && !string.IsNullOrWhiteSpace(filter.Value)) ? // is Color filter set?
selectedFilters.Any(filter =>
{
return (filter.Name == "Color" && shirt.Color == filter.Value);
}) : true)
&&
(selectedFilters.Any(filter => filter.Name == "Size" && !string.IsNullOrWhiteSpace(filter.Value)) ? // is Size filter set?
selectedFilters.Any(filter =>
{
return (filter.Name == "Size" && shirt.Size == filter.Value);
}) : true)
&&
(selectedFilters.Any(filter => filter.Name == "Type" && !string.IsNullOrWhiteSpace(filter.Value)) ? // is Type filter set?
selectedFilters.Any(filter =>
{
return (filter.Name == "Type" && shirt.Type == filter.Value);
}) : true)
);
});
model = filteredListOfShirts.ToList();
}
如果你有多个同名的过滤器值
{Name="Color",Value="Red"},{Name="Color",Value="Blue"}
您可以编写一个方法来检查给定的Shirt
是否在过滤器中,然后使用All
来检查每个。
public static void Filter(IList<SelectedFilter> selectedFilters)
{
var filters = selectedFilters
.GroupBy(i => i.Name);
var filteredShirts = db
.GetAllShirts()
.Where(shirt => filters.All(filter => ShirtInFilter(filter, shirt)));
}
public static bool ShirtInFilter(
IGrouping<string, SelectedFilter> filter,
Shirt shirt)
{
var values = filter.Select(i => i.Value);
switch (filter.Key)
{
case "Color":
return values.Contains(shirt.Color);
case "Size":
return values.Contains(shirt.Size);
case "Type":
return values.Contains(shirt.Type);
default:
return false;
}
}
如果您想使用反射访问属性,可以消除switch
,但对于您的用例来说,这似乎是多余的。