【发布时间】:2017-01-10 23:01:05
【问题描述】:
我正在尝试使用 linq 获取满足这些条件的所有菜单和子项:
- 菜单应具有链接或子项计数 > 0 以显示在
网站 - 对于有子菜单:它们应该至少有一个带有链接的子菜单
这是菜单类:
public class Menu
{
public string Name { get; set; }
public string Link { get; set; }
public List<Menu> Children { get; set; }
public Menu()
{
Children = new List<Menu>();
}
}
假设我们有这样的数据结构:
List<Menu> root = new List<Menu>();
Menu parent_1 = new Menu() { Name = "Parent 1", Link = null };
Menu parent_2 = new Menu() { Name = "Parent 2", Link = null };
//children for parent 1
Menu p1_child_1 = new Menu() { Name = "p1_child_1", Link = null };
Menu p1_child_2 = new Menu() { Name = "p1_child_2", Link = null };
//sub children of p1_child_2
Menu p1_child_1_1 = new Menu() { Name = "p1_child_1_1", Link = "l1-1" };
Menu p1_child_1_2 = new Menu() { Name = "p1_child_1_2", Link = null };
p1_child_1.Children.AddRange(new List<Menu> { p1_child_1_1 , p1_child_1_2 });
parent_1.Children.AddRange(new List<Menu> { p1_child_1, p1_child_2 });
Menu p2_child_1 = new Menu() { Name = "p2_child_1", Link = null };
Menu p2_child_2 = new Menu() { Name = "p2_child_2", Link = "l2-2" };
Menu p2_child_1_1 = new Menu() { Name = "p2_child_1_1", Link = null };
Menu p2_child_1_2 = new Menu() { Name = "p2_child_1_2", Link = null };
p2_child_1.Children.AddRange(new List<Menu> { p2_child_1_1, p2_child_1_2 });
parent_2.Children.AddRange(new List<Menu> { p2_child_1, p2_child_2 });
root.Add(parent_1);
root.Add(parent_2);
结果:根据请求的条件返回的过滤列表将是:
父_1
-
p1_child_1
- p1_child_1_1
父_2
- p2_child_2
考虑到菜单可能有多个级别,如何使用 Linq 或替代方法来实现这一点?
尝试了 cmets 中提出的解决方案,我添加了扩展方法
public static IEnumerable<TResult> SelectHierarchy<TResult>(this IEnumerable<TResult> source, Func<TResult, IEnumerable<TResult>> collectionSelector, Func<TResult, bool> predicate)
{
if (source == null)
{
yield break;
}
foreach (var item in source)
{
if (predicate(item))
{
yield return item;
}
var childResults = SelectHierarchy(collectionSelector(item), collectionSelector, predicate);
foreach (var childItem in childResults)
{
yield return childItem;
}
}
然后调用方法:
var result = root.SelectHierarchy(n => n.Children, n => n.Children.Count > 0 || n.Link != null).ToList();
但这不是我想要的,我希望有两个菜单带有满足我条件的子菜单,但我得到了 6 个我猜是扁平的菜单。
虽然,p2_child_1 被返回,因为孩子数 > 0,但它不应该导致它的菜单没有链接。 (我把谓词放在上面,因为我没有其他选择。
【问题讨论】:
-
Linq 不是为递归查询而设计的。您必须创建一些递归迭代的迭代器,然后查询 that。如果你有一些有用的东西,Linq 不会有很大帮助。
-
那么无论linq如何,如何以有效的方式做到这一点
-
您能否提供示例数据和预期输出作为有效的 C# 代码?因此,例如,如果您想将两个数字相加,您可以向我们提供:
int x = 3; int y = 5;,我想要结果int z = 8。然后,我们可以确定,当我们提供代码x + y时,我们知道我们会为您提供您想要的结果。 -
@Enigmativity 查看示例数据和期望的结果,很明显(对我而言)OP 有一个包含根节点的列表,并且希望获得一个新列表,其中删除了一些节点(如
child 1和child 1.1)。他还要求LINQ 或替代方法。但无论如何,我想你知道得更好:) -
@IvanStoev - 我很高兴得到纠正,但 OP 需要权衡他的实际要求。如果他 ping 我,我会在需要时重新打开。