Linq查询从树结构中选择项目但查看整个深度这是我制作的课程:publicclassItemTree{publicInt32id{得到;放;}[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]publicStringtext{get;放;}[JsonProperty(NullValueHandling=NullValueHandling.Ignore)]publicListitem{get;放;}publicintparentId{得到;放;下面是我如何使用它:vartree=newItemTree();树.id=0;tree.text="sometext";tree.item=newList();foreach(...){if(tree.item.Count==0){tree.item.Add(newItemTree{id=my_id,text=my_name,item=newList(),parentId=my_par});}else{tree.item.Where(x=>x.id==my_par).Select(x=>x.item).First().Add(newItemTree{id=my_id,text=my_name,item=new列表(),parentId=my_par});它在Where子句的行中崩溃。它崩溃的原因是:树有一个项目列表,我的查询只检查树的第一个项目,而不是他的孩子。我如何搜索树的整个深度并在那里添加项目?将树结构展平为列表可能很方便。如果您只有一个包含树的所有节点的IEnumerable,一些逻辑将更容易表达。您没有丢失任何信息,因为每个节点上仍然有父ID。这是一个自然递归的问题。使用递归lambda,尝试类似的东西:Func>flattener=null;flattener=t=>new[]{t}.Concat(t.item==null?Enumerable.Empty():t.item.SelectMany(child=>flattener(child)));需要注意的是,当你做这样一个递归的Func时,你必须先单独声明这个Func,然后将它设置为null。您还可以使用迭代器块方法展平列表:publicstaticIEnumerableFlatten(ItemTreenode){yieldreturnnode;if(node.item!=null){foreach(node.item中的varchild)foreach(Flatten(child)中的vardescendant)yieldreturndescendant;无论哪种方式,一旦树被展平,您可以在展平列表上执行简单的Linq查询以查找节点:flattener(tree).Where(t=>t.id==my_id);然后,要添加到树中,您可以执行以下操作:varitemOfInterest=flattenedTree.Where(t=>t.id==myId).Single();itemOfInterest.item=itemOfInterest.item??新列表();itemOfInterest.item.Add(myItemToAdd);使用我们的两种展平策略之一生成一个展平树。我还想指出,item不是列表属性的好名称。这些属性通常是复数形式(items)。此外,属性通常大写(Items)。这可能会有所帮助:publicstaticIEnumerableSelectRecursively(thisIEnumerablee,Func>memberSelector){foreach(Titemine){IEnumerableinner=memberSelector(item);if(inner!=null)inner.SelectRecursively(memberSelector);}}像这样使用它:Listtree=GetTree();列表flattenedTree=tree.SelectRecursively(T=>T.Items).ToList();这将启动递归选择(深度遍历),您可以在其中使用其他LinQ函数,例如.Where()。您正在使用First()而不是FirstOrDefault()。您应该执行以下操作。varitem=tree.item.Where(x=>x.id==my_par).Select(x=>x.item).FirstOrDefault();if(item!=null).Add(newItemTree{id=my_id,text=my_name,item=newList(),parentId=my_par});您应该在ItemTree中添加一个方法HasId此方法应该实现对特定ID的递归搜索,并使用(x=>x.HasId(my_par))为答案返回真或假您需要以某种方式递归树。一种解决方案是为ItemTree对象创建一个迭代器,如:计数==0))产量中断;foreach(varchildinitem){//首先返回子节点yieldreturnchild;//没有办法yield返回一个集合foreach(vargrandchildinchild.GetChildren()){yieldreturngrandchild;}}}}现在找到父级是微不足道的,就像varparent=tree.GetChilden().First(c=>c.id==my_par);parent.Add(newItemTree{id=my_id,text=my_name,item=newList(),parentId=my_par});从2013-06-1312:14解决@AgentFire的问题必须扩展到publicstaticIEnumerableSelectRecursively(thisIEnumerablee,Func>memberSelector){foreach(Titemine){yieldreturnitem;IEnumerableinner=memberSelector(item);if(inner!=null){foreach(TinnerItemininner.SelectRecursively(memberSelector)){yieldreturninnerItem;}}}}项目被放入结果列表。感谢@AgentFire提出这个好主意。以上就是C#学习教程:Linq查询从树结构中选取项,而是深入分享的检查全部内容。如果对你有用,需要了解更多C#学习教程,希望大家多加关注——本文来自网络合集,不代表立场,如涉及侵权,请点击右转联系管理员删除。如需转载请注明出处:
