在给定条件的情况下,如何从递归层次结构返回节点的路径?

大卫

我正在尝试创建一个linq扩展方法,该方法将路径返回到选定的节点。

节点Item4的路径将产生-{ Item1, Item2, Item4 }
节点Item3的路径将产生-{ Item1, Item3 }

public class Item
{
    public int Id { get; set; }
    public IList<Item> Items { get; set; }
}

Item1
    Item2
        Item4
    Item3

呼叫码

var path = myItem.Items
    .Path(e => e.Items, e => MyPredicateCondition())
    .ToList();

扩展方式

public static IEnumerable<T> Path<T>(
    this IEnumerable<T> source,
    Func<T, IEnumerable<T>> childrenSelector,
    Predicate<T> condition)
{
    if (source == null || !source.Any()) return default(T);

    var attempt = source.FirstOrDefault(t => condition(t));
    if (!Equals(attempt, default(T))) return attempt;

    var items = source.SelectMany(childrenSelector)
        .Path(childrenSelector, condition)
        .ToList();

    return attempt;
}

我的问题不是找到实际的节点,而是递归地返回节点将树备份到根节点。数据结构应保持原样-即,我不希望Item引用它parent item

注意:由于我尝试以其他方式使用IEnumerable yields等,因此当前代码无法编译。

效率不是问题,因为它将用于3或4个层次的深层,每个层次仅包含几个项目。

懒惰

这是一个Stack基于简单的实现。

想法是将要检查的每个项目放在堆栈上,如果它不是我们要查找的路径的一部分,请从堆栈中将其删除,直到找到要查找的项目为止。

IEnumerable<T> Path<T>(IEnumerable<T> source,
                       Func<T, IEnumerable<T>> childrenSelector,
                       Func<T, bool> condition)
{
    var path = new Stack<T>();
    Path(source, childrenSelector, condition, path);
    return path.Reverse().ToList();
}                       
bool Path<T>(IEnumerable<T> source,
             Func<T, IEnumerable<T>> childrenSelector,
             Func<T, bool> condition,
             Stack<T> path)
{
    foreach (var item in source)
    {
        path.Push(item);
        if (condition(item) || Path(childrenSelector(item), childrenSelector, condition, path))
            return true;
        else
            path.Pop();
    }
    return false;
}

例子:

Item[] items = { new Item {Id = 1, Items = new List<Item> 
{ 
    new Item {Id = 2,  Items = new List<Item> {new Item { Id = 4, Items = new List<Item>()}}},
    new Item {Id = 3,  Items = new List<Item>()},
}}};

var path = Path(items, e => e.Items, e => e.Id == 4);

// prints '1 -> 2 -> 4'
Console.WriteLine(String.Join(" -> ", path.Select(i=>i.Id)));

本文收集自互联网,转载请注明来源。

如有侵权,请联系 [email protected] 删除。

编辑于
0

我来说两句

0 条评论
登录 后参与评论

相关文章

Python 3.5+:如何在给定完整文件路径的情况下动态导入模块(存在隐式同级导入)?

Python 3.4:如何在给定完整路径的情况下导入模块?

有没有一种方法只能在给定条件的情况下使用递归类型绑定字段?

在给定一组预定键的情况下,如何对键进行重新排序,以便在插入B树时使用最少数量的节点?

postgres:在给定条件的情况下如何计算数组列中的不同元素

为什么此函数在给定右值参数的情况下返回左值引用?

在给定具有R的位置和条件的情况下更改向量中的值

熊猫在给定多个条件的情况下计算多个列的总和

如何在给定点的情况下绘制区域?

在给定基数的情况下,如何恢复其MRO?

Neo4j在给定子节点集的情况下计算连接最紧密的父节点

递归获取嵌套对象中给定节点的完整路径(父级层次结构)

如何在给定FrameworkElement的情况下检索CompositionEffect?

如何在Scala中在给定条件的情况下合并两个数据帧中的行?

在给定特定条件的情况下,如何使图像显示在HTML中?

在给定起点和终点的情况下检查字符串列表中的路径

在python中,如何最好地在给定变量路径和值的情况下将key:value插入json

在给定约束的情况下,如何查找数组中2个元素的最大差?

如何在给定行条件的情况下从表中选择所有行?

在给定的数据库结构可以在运行时更改的情况下,如何处理并发的SQL更新

MATLAB:如何在给定数字数组的情况下评估符号函数,并返回结果数组?

递归。在给定起点和最大距离的情况下找到所有最长的路径

python-在给定条件的情况下找到列表中下一项的位置

在给定目录结构的情况下如何导入python模块

在给定新名称列表的情况下,如何重命名一组目录?

在不使用类/对象的情况下递归创建树层次结构

如何在给定员工的 EmployeeID 值作为 IN 参数的情况下返回员工的工资等级

如何在给定具有条件的数据帧的情况下改变列?

如何在给定完整路径的情况下导入模块?