递归获取ID

时间:2011-10-25 08:55:14

标签: c# list children

haloa!

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

public class Channel 
{
    public long ID { get; set; }
    public long parentID { get; set; }
}
strcuture可以是这样的:

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

3 个答案:

答案 0 :(得分:2)

让所有孩子:

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>个孩子来建模。

答案 1 :(得分:1)

不知道Marcos的回答是否真的产生了预期的结果,但我会用更加LINQish的方式来写这个:

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

但请注意,它不检查循环冗余,最终可能会出现堆栈溢出异常!

答案 2 :(得分:0)

具有

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