从树中递归删除项目

时间:2011-10-12 17:48:18

标签: linq recursion

我有一个具有以下结构的树视图:

var myTree = myRepository.GetTree();

对象文件夹以这种方式构建:

public class Folder
{
   public string Name { get; set; }
   public List<Folder> Folders { get; set; }
   public Folder Parent { get; set; }
}

假设存储库正在向我返回类似这样的结构:

MyFolder
   -MyChild01
   -MyChild02
      -MySubChild01       
   -MyChild03
      -MySubChild02

我需要以递归方式读取树中的所有项目,如果项目的名称包含“02”我必须从树中删除该项目。所以最终的结果应该是:

MyFolder
   -MyChild01
   -MyChild03

我想看看如何使用带有匿名委托的递归LINQ或递归函数来执行此操作。

2 个答案:

答案 0 :(得分:5)

您可以采取多种方法来实现这一目标。

最简单的方法是采用功能方法并以递归方式重建树,排除与您的模式匹配的文件夹。

static Folder Filtered(Folder root, Func<Folder, bool> predicate)
{
    return new Folder
    {
        Name = root.Name,
        Parent = root.Parent,
        Folders = root.Folders
            .Where(predicate)
            .Select(subFolder => Filtered(subFolder, predicate))
            .ToList(),
    };
}

Folder myTree = ...;
var filtered = Filtered(myTree, f => f.Name.Contains("02"));

如果出于某种原因您不想创建文件夹的新实例但宁愿修改现有实例,则必须进行一些调整,但仍然同样简单。

static Folder Filtered(Folder root, Func<Folder, bool> predicate)
{
    // make use of the RemoveAll() method for lists
    root.Folders.RemoveAll(subFolder => !predicate(subFolder));
    foreach (var subFolder in root.Folders)
    {
        Filtered(subFolder, predicate);
    }
    return root;
}

答案 1 :(得分:1)

    static void Main(string[] args)
    {
        var root = new Folder()
        {
            Name = "MyFolder",
            Folders = new List<Folder>(){
                    new Folder() {Name="MyChild01", Folders = new List<Folder>()},
                    new Folder() {Name="MyChild02", Folders = new List<Folder>(){
                        new Folder() { Name="MySubChild01", Folders = new List<Folder>()}}
                    },
                    new Folder() {Name="MyChild03", Folders = new List<Folder>(){
                        new Folder() { Name="MySubChild02", Folders = new List<Folder>()}}
                    },
                }
        };

        var filtered = applyFilter(root, f=>!f.Name.EndsWith("02"));

    }

    static Folder applyFilter( Folder root, Predicate<Folder> filter )
    {
        var result = new Folder() { Name = root.Name, Parent = root.Parent };
        result.Folders = (from child in root.Folders
                         where filter(child)
                         select applyFilter(child, filter)).ToList();
        return result;
    }