递归获取ID

发布于 2024-12-11 15:32:59 字数 555 浏览 0 评论 0原文

哈啰!

我有一个 List 其中 Channel 是一个自定义类 offcourse:

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

haloa!

i have a List<Channel> where Channel is a custom class offcourse:

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

strcuture can be something like:

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

and so on.

what i would like to do is get all children ID's of a specific channel:

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

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

瑶笙 2024-12-18 15:32:59

要获取所有子项:

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

将其构建为返回 IEnumerable,而不是返回 List,然后调用需要 List的代码。 可以使用 new List(GetChildren(list, id))GetChildren(list, id).ToList(),而调用不需要此功能的代码时,可以通过不构建实际上不需要的列表来获得更好的内存性能和获得第一个结果的时间,如 foreach( GetChildren(list, id)) 中的长 childID

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

假设不能重复(通过多个路由的同一个孙子):

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

To get all children:

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

Build this as returning an IEnumerable<long> rather than returning a List<long> as then calling code that needs a List<long> can use either new List<long>(GetChildren(list, id)) or GetChildren(list, id).ToList(), while calling code that doesn't need this can get better performance in memory and time to first result by not building a list it doesn't actually need, as in foreach(long childID in GetChildren(list, id)).

To get all descendants (children, grandchildren, great-grandchildren, etc.) which is the only case we could make any use of recursion (as per your question title) use:

Assuming there cannot be duplicates (same grandchild through multiple routes):

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

If there can be duplicates then you could apply .Distinct() to the above, or go for:

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

This said, I would probably rather model this by having the Channel classes maintain a List<Channel> of children.

笑脸一如从前 2024-12-18 15:32:59

不知道 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);
}

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

Don't know if Marcos answer really produces the desired result, but i would write this in a more LINQish fashion:

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

If you also need the deep nested ones you could maybe use this function:

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

But be aware that it doesn't check for cyclic redundancy and could end up in an stackoverflow exception!

逆夏时光 2024-12-18 15:32:59

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

Having

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

in your class, you can do:

No recursion (so only children)

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

or with recursion (children of children too)

private List<long> GetChildrenIds(long parentId)
{
    list.ForEach(p => { if (p.parentID == parentId) { 
                            ret.Add(p.ID); 
                            GetChildrenIds(p.ID); 
                        } 
                      });
    return ret;
}
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文