有没有更好的方法来编写 LINQ 函数?
Is there a better way to write a LINQ function?
所以,我是 LINQ 的新手,正在尝试弄清楚如何过滤项目。
那是我的任务
public async Task<PagedList<Item>> GetItems (ItemParams itemParams) {
var items = _context.Items.AsQueryable ();
if (itemParams.CategoryId > 0) {
var category = GetCategory (itemParams.CategoryId);
items = items.Where (i => FilterItems (i, category.Result));
}
return await PagedList<Item>.CreatAsync (items, itemParams.PageNumber, itemParams.PageSize);
}
决定要return哪些项目的函数是
static bool FilterItems (Item item, Category category) {
if (item.CategoryId == category.Id) {
return true;
}
if (category.Children.Count > 0) {
foreach (Category cat in category.Children) {
return FilterItems (item, cat);
}
}
return false;
}
获取类别函数
public async Task<Category> GetCategory (int? id) {
if (id == null) {
return null;
}
var categories = _context.Categories.Include (x => x.Children).AsEnumerable ().Where (c => c.Id == id);
categories = Traverse (categories);
var category = await Task.FromResult (categories.First (c => c.Id == id));
return category;
}
您的过滤器将无法按预期工作,因为第一个循环中的 foreach
returns。还有这个名字 FilterItems
不直观。
static bool ContainsItem(Category category, Item item)
{
return
category.Id == item.CategoryId ||
category.Children.Any(c => ContainsItem(c, item);
}
由于 C# 对 || Operator 执行短路计算,因此如果第一项匹配,则不会计算第二项。请注意,这不是肮脏的把戏,而是 C# 规范的一部分。
从代码来看,如果项目在当前类别或任何子类别中,似乎 FilterItems()
returns 为真?
如果是这样,我认为您当前的代码有问题:对 FilterItems()
returns 的递归调用会立即产生第一个子类别的结果,而不会检查其他子类别
修改后的代码如下:
public static bool InCategoryOrSubCategory(Item item, Category category)
{
return item.CategoryId == category.Id ||
category.Children.Any(subCategory => InCategoryOrSubCategory(item, subCategory));
}
我把名字改成InCategoryOrSubCategory
,这样更清楚
这是一个柯里化版本,使 Where
调用稍微好一点(但方法本身有点神秘):
public static Func<Item, bool> InCategoryOrSubCategory(Category category)
{
return item =>
item.CategoryId == category.Id ||
category.Children.Any(subCategory => InCategoryOrSubCategory(subCategory)(item));
}
用法:
items.Where(InCategoryOrSubCategory(category))
所以,我是 LINQ 的新手,正在尝试弄清楚如何过滤项目。 那是我的任务
public async Task<PagedList<Item>> GetItems (ItemParams itemParams) {
var items = _context.Items.AsQueryable ();
if (itemParams.CategoryId > 0) {
var category = GetCategory (itemParams.CategoryId);
items = items.Where (i => FilterItems (i, category.Result));
}
return await PagedList<Item>.CreatAsync (items, itemParams.PageNumber, itemParams.PageSize);
}
决定要return哪些项目的函数是
static bool FilterItems (Item item, Category category) {
if (item.CategoryId == category.Id) {
return true;
}
if (category.Children.Count > 0) {
foreach (Category cat in category.Children) {
return FilterItems (item, cat);
}
}
return false;
}
获取类别函数
public async Task<Category> GetCategory (int? id) {
if (id == null) {
return null;
}
var categories = _context.Categories.Include (x => x.Children).AsEnumerable ().Where (c => c.Id == id);
categories = Traverse (categories);
var category = await Task.FromResult (categories.First (c => c.Id == id));
return category;
}
您的过滤器将无法按预期工作,因为第一个循环中的 foreach
returns。还有这个名字 FilterItems
不直观。
static bool ContainsItem(Category category, Item item)
{
return
category.Id == item.CategoryId ||
category.Children.Any(c => ContainsItem(c, item);
}
由于 C# 对 || Operator 执行短路计算,因此如果第一项匹配,则不会计算第二项。请注意,这不是肮脏的把戏,而是 C# 规范的一部分。
从代码来看,如果项目在当前类别或任何子类别中,似乎 FilterItems()
returns 为真?
如果是这样,我认为您当前的代码有问题:对 FilterItems()
returns 的递归调用会立即产生第一个子类别的结果,而不会检查其他子类别
修改后的代码如下:
public static bool InCategoryOrSubCategory(Item item, Category category)
{
return item.CategoryId == category.Id ||
category.Children.Any(subCategory => InCategoryOrSubCategory(item, subCategory));
}
我把名字改成InCategoryOrSubCategory
,这样更清楚
这是一个柯里化版本,使 Where
调用稍微好一点(但方法本身有点神秘):
public static Func<Item, bool> InCategoryOrSubCategory(Category category)
{
return item =>
item.CategoryId == category.Id ||
category.Children.Any(subCategory => InCategoryOrSubCategory(subCategory)(item));
}
用法:
items.Where(InCategoryOrSubCategory(category))