2011-10-12 125 views
3

删除项目我有以下结构的树形视图:递归从树

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与匿名委托或用递归函数来做到这一点。

回答

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; 
} 
+0

我打算选择这一个,因为我无法进行更改并创建新的实例,但我必须保持现有实例已过滤,并且此文章解释了这一点。 – Raffaeu

+0

辉煌 - 正是我期待的(第二个例子)谢谢! –

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; 
    }