如何在这样的树结构中获取父节点

时间:2016-04-15 12:51:39

标签: c# linq

当树结构如下时,如何获得父项:

[HttpGet]
public ActionResult GetResults()
{
    var dataFromStoredProc=db.Search(Country, state, city, str);

    // Translate the addressSerachResultModel to AddressSearchResultModel
    var addressSearchResultModel= new AddressSearchResultModel();
    var addressModel= new AddressModel()
    foreach(var item in dataFromStoredProc )
    {
        //Assing every property from the dataFromStoredProc to AddressModel
        //and add it to the list
        addressSearchResultModel.Add(AddressModel);
    }

    return View(addressSearchResultModel);       
}

我们说我们不能在这个类中添加父元素项(public TreeModel Parent {get; set;})。

修改

如何从m1获取元素m22(ID = 22)父m2(ID = 2)?我认为我们可以迭代m1并在条件合适时以某种方式返回父。

public class TreeModel
{
    public int ID { get; set; }
    public List<TreeModel> Children { get; set; }
}

5 个答案:

答案 0 :(得分:1)

public IEnumerable<TreeModel> GetAllDescendants(IEnumerable<TreeModel> rootNodes)
{
    var descendants = rootNodes.SelectMany(_ => GetAllDescendants(_.Children));
    return rootNodes.Concat(descendants);
}


public static TreeModel GetParent(this TreeModel rootNode, Func<TreeModel, bool> childSelector)
{
    var allNodes = GetAllDescendants(new [] { rootNode });
    var parentsOfSelectedChildren = allNodes.Where(node => node.Children.Any(childSelector));

    return parentsOfSelectedChildren.Single();
}

m1.GetParent(_ => _.ID == 22);
  1. 获取所有节点的平面列表
  2. 在此列表中搜索直接子节点包含m22
  3. 的节点

答案 1 :(得分:0)

怎么样:

public class SaneTreeModel:  TreeModel
{
  public SaneTreeModel Parent { get; set; }
}
}

答案 2 :(得分:0)

绝对不是,有了这样的子节点,你无法得到它的父节点。仅仅因为没有任何参考。

要获取节点的父节点,您必须添加父节点或将引用保存在其他位置(通过变量或其他内容)。

修改

@Zulis如果从根节点进行搜索,您肯定可以找到所需的节点。但正如我所说,只有孩子节点,你不能这样做。

但我认为你应该避免搜索,因为那会很慢

答案 3 :(得分:0)

我会先找到满足条件的第一个元素(在你的例子中为ID == 22),然后找到这个元素的父元素。不是最好的解决方案,但也许您将需要单独使用它们。

always

如果将此代码块放在TreeModel类中,则您提供的示例将返回m2

答案 4 :(得分:0)

使用此代码模式。它简化了代码,因为您不必向子节点显式添加节点,并且每个节点都知道其父节点是谁以及子节点是谁。它也是所有类型安全的。

class Program
{
    static void Main(string[] args)
    {
        var m1=new TreeModel() { ID=1 };
        var m2=new TreeModel(m1) { ID=2 };
        var m21=new TreeModel(m2) { ID=21 };
        var m22=new TreeModel(m2) { ID=22};
        var m3=new TreeModel(m1) { ID=3 };

        var item=m1.RecursiveFind((p) => p.ID==22);
        var parent=item.Parent;
        // parent.ID == 2
        var root=item.Root;
        // root.ID == 1;
    }
}

public class TreeModel : Tree<TreeModel>
{
    public int ID { get; set; }
    public TreeModel() { }
    public TreeModel(TreeModel parent) : base(parent) { }
}

public class Tree<T> where T : Tree<T>
{
    protected Tree() : this(null) { }
    protected Tree(T parent)
    {
        Parent=parent;
        Children=new List<T>();
        if(parent!=null)
        {
            parent.Children.Add(this as T);
        }
    }
    public T Parent { get; set; }
    public List<T> Children { get; set; }
    public bool IsRoot { get { return Parent==null; } }
    public T Root { get { return IsRoot?this as T:Parent.Root; } }
    public T RecursiveFind(Predicate<T> check)
    {
        if(check(this as T)) return this as T;
        foreach(var item in Children)
        {
            var result=item.RecursiveFind(check);
            if(result!=null)
            {
                return result;
            }
        }
        return null;
    }
}

当您从Tree<T>派生时,您可以创建自定义树结构,您可以设计节点类(此处为TreeModel)以及如何在需要时处理父项,子项和兄弟项。