C#linq层次结构列表属性集

时间:2016-10-27 12:28:50

标签: c# linq

我有以下课程:

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

3 个答案:

答案 0 :(得分:1)

所以你只需要把它放在一个递归函数中。像这样:

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

答案 1 :(得分:1)

一般情况中,如果您需要使用这样的图表进行大量工作,我建议实施 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) {  
  ...
} 

答案 2 :(得分:0)

假设您只有一个单位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);