迭代一棵树并让某些孩子进入C#

时间:2017-10-22 09:27:47

标签: c# recursion observablecollection

我目前正在使用像这样定义的树结构

public class TreeNode
{
   private ObservableCollection<TreeItem> nodeItems;
   private ObservableCollection<TreeNode> nodeChildren;
   //public "NodeItems" and "NodeChildren" getters and setters
}

public class TreeItem
{
   private bool isSelected;
   private string Name;
   //public "IsSelected" and "Name" getters and setters
}

public class Tree
{
   private TreeNode rootNode;
   //public getters and setters properties
}

我正在尝试编写一个函数或public属性,递归获取nodeItemsTree的所有isSelected == true并使其成为一个扁平集合

所以我在TreeNode类中编写了这个函数,递归地遍历了孩子:

public ObservableCollection<TreeItem> SelectedItems()
    {
        ObservableCollection<TreeItem> tempCollection = new ObservableCollection<TreeItem>();
        if (nodeItems != null)
        {
            foreach (TreeItem item in nodeItems)
            {
                if (item.IsSelected == true)
                {
                    tempCollection.Add(item);
                }
            }
        }
        if (nodeChildren != null)
        {
            foreach (TreeNode node in nodeChildren)
            {
                tempCollection.Concat(node.SelectedItem()); 
            }
        }
        return tempCollection;
    }

总是在最后返回一个空集合

我如何纠正它,并可能改进它(使用 Lambda 表达式或属性)?

2 个答案:

答案 0 :(得分:1)

Concat上的ObservableCollection函数不会修改任何参数。您必须将结果对象分配给tempCollection

    if (nodeChildren != null)
    {
        foreach (TreeNode node in nodeChildren)
        {
            tempCollection = new ObservableCollection<TreeNode>(tempCollection.Concat(node.SelectedItem())); 
        }
    }

编辑:或者,您可以使用重载的私有方法来不使用这么多临时集合:

public ObservableCollection<TreeItem> SelectedItems()
{
    ObservableCollection<TreeItem> toReturn = new ObservableCollection<TreeItem>();
    SelectedItems(toReturn);
    return toReturn;
}

private void SelectedItems(ObservableCollection<TreeItem> tempCollection)
{
    if (nodeItems != null)
    {
        foreach (TreeItem item in nodeItems)
        {
            if (item.IsSelected == true)
            {
                tempCollection.Add(item);
            }
        }
    }
    if (nodeChildren != null)
    {
        foreach (TreeNode node in nodeChildren)
        {
            node.SelectedItems(tempCollection);
        }
    }
}

答案 1 :(得分:1)

您可以将树的定义简化为:

public class Tree : ObservableCollection<Tree>
{
    public ObservableCollection<TreeItem> nodeItems;
}

现在你可以这样做:

public IEnumerable<TreeItem> FlattenIsSelected(Tree tree)
{
    return tree.nodeItems.Where(x => x.isSelected)
        .Concat(tree.SelectMany(t => FlattenIsSelected(t)));
}

如果你保持现有的定义,这并不困难。

相关问题