gpt4 book ai didi

linq - 使用递归过滤 LINQ 上的集合

转载 作者:行者123 更新时间:2023-12-04 06:07:47 26 4
gpt4 key购买 nike

我有一个名为 的集合菜单项集合 而这个派生形式 列表<菜单项>

有一个 的单例实例菜单项集合 如果我简化 的字段菜单项 :

public class MenuItem
{
int Id {set;get;}
string Title {set;get;}
MenuItemCollection ChildMenus {set;get;}
}

我需要使用 过滤器 这个集合的方法。例如,我想过滤一个菜单 ID 的集合。
这是一个示例 MenuItemCollection:
1-Home
2-User Menu
4-Update Info
5-Delete Account
3-News
6-Archived News

正如你所看到的,有一些 child 菜单,如数字 4 或数字 6

我通常使用下面的过滤器:
public List<MenuItem> Filter(MenuItemFilterArgs args)
{
List<MenuItem> Result = new List<MenuItem>();
IQueryable<MenuItem> QueryableTemp = this.AsQueryable();

return (from item in QueryableTemp
orderby item.Ordering descending
select item).ToList<MenuItem>();
}

并将此方法调用为:
var FilteredMenus = MenuItemCollection.GetInstance.Filter(new MenuItemFilterArgs { Id = 5 });

由于编号 5 位于编号 2 菜单项下的内部集合中,因此结果返回为 0。无法找到。

如何通过内部 MenuItemCollections 递归运行过滤器?你能写一个代码示例吗?

PS: If you must know why I'm using a singleton instance; my idea was to retrieve the menus from database and keep it as an object for easier and faster usage on run-time.



任何帮助将不胜感激。
提前致谢

最佳答案

这是一个工作示例。 ExtensionMethods.Map 方法正是您所需要的。

using System;
using System.Collections.Generic;
using System.Linq;
using System.Linq.Expressions;

namespace WindowsFormsApplication1
{
static class Program
{
[STAThread]
static void Main()
{
var menuItems1 = MenuItemCollection.Instance.Filter(null);
var menuItems2 = MenuItemCollection.Instance.Filter(new MenuItemCriteria { Id = 5 });
var menuItems3 = MenuItemCollection.Instance.Filter(new MenuItemCriteria { Title = "News" });
var menuItems4 = MenuItemCollection.Instance.Filter(new MenuItemCriteria { Title = "News", IsTrash = true });
}
}

public class MenuItemCollection : List<MenuItem>
{
public static readonly MenuItemCollection Instance;

static MenuItemCollection()
{
Instance = GetMenuList();
}

static MenuItemCollection GetMenuList()
{
return new MenuItemCollection {
new MenuItem {Id = 1, Title = "Home"},
new MenuItem {Id = 2, Title = "User Menu", ChildMenus = new MenuItemCollection {
new MenuItem { Id = 4, Title = "Update Info"},
new MenuItem { Id = 5, Title = "Delete"}
}},
new MenuItem {Id = 3, Title = "News", ChildMenus = new MenuItemCollection {
new MenuItem { Id = 6, Title = "Archived News"},
new MenuItem { Id = 6, Title = "Trashy News", IsTrash = true}
}},
};
}

public List<MenuItem> Filter(MenuItemCriteria criteria)
{
var expression = PredicateBuilder.True<MenuItem>();

if(criteria != null)
{
if (criteria.Id.HasValue)
{
expression = expression.And(menuItem => menuItem.Id == criteria.Id);
}

if (!string.IsNullOrEmpty(criteria.Title))
{
expression = expression.And(menuItem => menuItem.Title.Contains(criteria.Title));
}

if (criteria.IsTrash.HasValue)
{
expression = expression.And(menuItem => menuItem.IsTrash == criteria.IsTrash);
}
}

Func<MenuItem, bool> searchCriteria = expression.Compile();
Func<MenuItem, IEnumerable<MenuItem>> childrenSelector = x => x.ChildMenus;

return this.Map(searchCriteria, childrenSelector).ToList();
}
}

public class MenuItemCriteria
{
public int? Id { set; get; }
public string Title { set; get; }
public bool? IsTrash { set; get; }
}

public class MenuItem
{
public int Id { set; get; }
public string Title { set; get; }
public bool IsTrash { set; get; }
public MenuItemCollection ChildMenus { set; get; }
}

public static class ExtensionMethods
{
public static IEnumerable<T> Map<T>(this IEnumerable<T> source,
Func<T, bool> selector = null,
Func<T, IEnumerable<T>> childrenSelector = null)
{
if (source == null) return new List<T>();

if (selector == null)
{
// create a default selector that selects all items
selector = x => true;
}

var list = source.Where(selector);

if (childrenSelector != null)
{
foreach (var item in source)
{
list = list.Concat(childrenSelector(item).Map(selector, childrenSelector));
}
}

return list;
}
}

public static class PredicateBuilder
{
public static Expression<Func<T, bool>> True<T>() { return f => true; }
public static Expression<Func<T, bool>> False<T>() { return f => false; }

public static Expression<Func<T, bool>> Or<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.OrElse(expr1.Body, invokedExpr), expr1.Parameters);
}

public static Expression<Func<T, bool>> And<T>(this Expression<Func<T, bool>> expr1,
Expression<Func<T, bool>> expr2)
{
var invokedExpr = Expression.Invoke(expr2, expr1.Parameters.Cast<Expression>());
return Expression.Lambda<Func<T, bool>>
(Expression.AndAlso(expr1.Body, invokedExpr), expr1.Parameters);
}
}
}

关于linq - 使用递归过滤 LINQ 上的集合,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/8153835/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com