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

c# linq分层列表属性集

你只需要把它放到递归函数中。像这样:

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