递归获取ID

本文关键字:ID 获取 递归 | 更新日期: 2023-09-27 18:12:24

哈哈!

我有一个List<Channel>,其中Channel是一个自定义类:

public class Channel 
{
    public long ID { get; set; }
    public long parentID { get; set; }
}

结构可以类似于:

ID = 1, parentID = 0
    ID = 64, parentID = 1
        ID = 28, parentID = 64
        ID = 36, parentID = 64
ID = 5, parentID = 0

等等

我想做的是获取特定频道的所有儿童ID:

function List<long> getChildrenIDS (long ID)
{
    // WHAT GOES HERE?
}

递归获取ID

获取所有子项:

public IEnumerable<long> GetChildren(List<Channel> list, long id)
{
  foreach(Channel c in list)
    if(c.parentID == id)
      yield return c.ID;
}

将其构建为返回IEnumerable<long>,而不是返回List<long>,因为需要List<long>的调用代码可以使用new List<long>(GetChildren(list, id))GetChildren(list, id).ToList(),而不需要foreach(long childID in GetChildren(list, id))的调用代码则可以通过不构建实际上不需要的列表来获得更好的内存性能和第一次结果的时间。

要获得所有后代(子女、孙子、曾孙等(,这是我们唯一可以使用递归的情况(根据您的问题标题(,请使用:

假设不能有重复(通过多条路线的同一个孙子(:

private IEnumerable<long> GetDescendants(List<Channel> list, long id)
{
   foreach(long child in GetChildren(list, id))
   {
     yield return child;
     foreach(long grandchild in GetDescendants(list, child))
       yield return grandchild;
   }
}

如果可能存在重复,那么您可以将.Distinct()应用于以上内容,或者选择:

private IEnumerable<long> GetDescHelper(List<Channel> list, long id, HashSet<long> already)
{
  foreach(long child in GetChildren(list, id))
    if(already.Add(child))
    {
      yield return child;
      foreach(long desc in GetDescHelper(list, child, already))
        yield return desc;
    }
}
public IEnumerable<long> GetDescendants(List<Channel> list, long id)
{
  return GetDescHelper(list, id, new HashSet<long>());
}

也就是说,我可能更愿意通过让Channel类维护儿童的List<Channel>来对此进行建模。

不知道Marcos的回答是否真的产生了所需的结果,但我会用一种更林奇的方式写这篇文章:

private IEnumerable<long> GetChildrenIds(IEnumerable<Channel> channels, long parentId)
{
    if(channels == null)
        throw new ArgumentNullException("channels");
    var childs = channels.Where(c => c.ParentId == parentId)
                         .Select(c => c.Id);
    return childs;
}

如果你也需要深度嵌套的,你可以使用这个函数:

private IEnumerable<long> GetAllChildrenIds(IEnumerable<Channel> channels, long parentId)
{
    var childs = GetChildrenIds(channels, parentId);
    var alldescendants = childs.SelectMany(id => GetAllChildrenIds(channels, id));
    return childs.Concat(alldescendants);
}

但请注意,它不会检查循环冗余,可能会导致stackoverflow异常!

具有

List<Channel> list = new List<Channel>();
List<long> ret = new List<long>();

在你的课堂上,你可以做:

没有递归(所以只有子级(

private List<long> GetChildrenIds(long parentId)
{
    list.ForEach(p => { if (p.parentID == parentId) ret.Add(p.ID); });
    return ret;
}

或使用递归(子代也是(

private List<long> GetChildrenIds(long parentId)
{
    list.ForEach(p => { if (p.parentID == parentId) { 
                            ret.Add(p.ID); 
                            GetChildrenIds(p.ID); 
                        } 
                      });
    return ret;
}