c# linq分层列表属性集
本文关键字:属性 列表 分层 linq | 更新日期: 2023-09-27 18:15:19
我有以下类:
public class Products
{
public int ID { get; set; }
public int KeyID { get; set; }
public int KeyLevel { get; set; }
public string COMBasis { get; set; }
}
这里ID是主键,KeyID包含该项的父ID。KeyLevel包含层次树中节点的级别。如果父属性被更改,我必须为所有子属性设置COMBasis属性。我怎样才能得到孩子们呢?
以下是我已经在做的,但我被卡在KeyLevel部分后:
foreach (Products prod in ProductList.Where(x => x.KeyID == prd.ID))
{
while(prod.KeyLevel!=6)
prod.COMStandard = prd.COMStandard;
}
你只需要把它放到递归函数中。像这样:
void ApplyCOMBasis(List<Products> productList, int pId, string comStandard)
{
foreach (Products prod in productList.Where(x => x.KeyID == pId))
{
prod.COMStandard = comStandard;
ApplyCOMBasis(productList, prod, comStandard);
}
}
你可以这样调用(基于你当前的代码):
ApplyCOMBasis(ProductList, prd.ID, prd.COMBasis);
在一般情况下,如果你必须大量处理这样的图,我建议实现BFS (广度优先搜索)算法:
public static IEnumerable<T> BreadthFirst<T>(this IEnumerable<T> source,
Func<T, IEnumerable<T>> children) {
if (Object.ReferenceEquals(null, source))
throw new ArgumentNullException(nameof(source));
else if (Object.ReferenceEquals(null, children))
throw new ArgumentNullException(nameof(children));
HashSet<T> proceeded = new HashSet<T>();
Queue<IEnumerable<T>> queue = new Queue<IEnumerable<T>>();
queue.Enqueue(source);
while (queue.Count > 0) {
IEnumerable<T> src = queue.Dequeue();
if (Object.ReferenceEquals(null, src))
continue;
foreach (var item in src)
if (proceeded.Add(item)) {
yield return item;
queue.Enqueue(children(item));
}
}
}
实现BFS后,您所要做的就是指定初始节点和规则如何获得给定节点的子节点:
var products = ProductList
.Where(prd => prd.ID == ...) // initial nodes
.BreadthFirst(parent => ProductList.Where(item => item.ID == parent.KeyID));
foreach (Products prod in products) {
...
}
假设您只有一个扁平的List<Products>
,并且您需要将其作为层次结构进行搜索,那么您将需要递归调用。
void UpdateChildren(List<Products> list, int keyId, string value)
{
// find the items with this KeyID
var children = list.Where(i => i.KeyId = keyId)
foreach(var p in children)
{
p.COMBasis = value;
UpdateChildren(list, p.ID, value);
}
}
当你需要更新父元素时你像这样开始
var item = list.Single(x => x.ID = id); // assume you know the id of the parent
item.COMBasis = newCOMBasis;
UpdateChildren(item, item.ID, newCOMBasis);