简体   繁体   English

C#Linq分层列表属性集

[英]C# linq hierarchical list property set

I have the following class: 我有以下课程:

public class Products
{
    public int ID { get; set; }
    public int KeyID { get; set; }    
    public int KeyLevel { get; set; }    
    public string COMBasis { get; set; }            
}

Here ID is the primary key and KeyID contains the parent ID of the item. 这里的ID是主键,而KeyID包含该项的父ID。 KeyLevel contains the level of the node in the hierarchical tree. KeyLevel包含层次结构树中节点的级别。 I have to set the COMBasis property for all the children if the parent's property is changed. 如果更改了父级的属性,则必须为所有子级设置COMBasis属性。 How can I get the children? 我怎样才能得到孩子?

Following is what I am already doing but I am stuck in the after KeyLevel part: 以下是我已经在做的事情,但是我陷入了KeyLevel之后的问题:

foreach (Products prod in ProductList.Where(x => x.KeyID == prd.ID))
{
    while(prod.KeyLevel!=6)
    prod.COMStandard = prd.COMStandard;    
}

So you just need to put that in a recursive function. 因此,您只需要将其放在递归函数中即可。 Something like this: 像这样:

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

Which you can then call like this (based on your current code): 然后您可以像这样调用它(基于当前代码):

ApplyCOMBasis(ProductList, prd.ID, prd.COMBasis);

In general case , if you have to work a lot with such a graph, I suggest implementing a BFS ( Breadth First Search ) algorithm: 通常 ,如果您需要处理大量此类图,建议您实施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));
      }
  }
}

Having BFS implemented, all you have to do is to specify initial nodes and a rule how to obtain children for a given node: 实施BFS后 ,您要做的就是指定初始节点以及如何为给定节点获取子代的规则

var products = ProductList 
  .Where(prd => prd.ID == ...) // initial nodes
  .BreadthFirst(parent => ProductList.Where(item => item.ID == parent.KeyID));

foreach (Products prod in products) {  
  ...
} 

Assumping you just have a flat List<Products> and you need to search it as a hierarchy, you'll need a recursive call. 假设您只有一个平面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);
   }
} 

So when you need to update the parent you start like this 因此,当您需要更新父级时,您将像这样开始

var item = list.Single(x => x.ID = id); // assume you know the id of the parent
item.COMBasis = newCOMBasis;
UpdateChildren(item, item.ID, newCOMBasis);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM