c# - 返回具有分配的所有子项的新列表的函数 VS 返回该列表的子项但未分配的函数
问题描述
我正在尝试找出一种方法来遍历对象的所有子项(包括子项的子项)而不创建垃圾分配。
我之前的函数是一个返回列表的递归函数。
现在我有两个函数,一个返回一个计数,另一个在某个索引处获取孩子。
我觉得可能有更好的方法来遍历一个对象的所有孩子
这是一个比较递归列表和递归计数 + getAt(index) 的示例代码
public class MyClassWithChildren
{
private MyClassWithChildren[] m_Children;
//With allocation
public IReadOnlyList<MyClassWithChildren> GetAllChildren(bool includeThis = false)
{
var allChildren = new List<MyClassWithChildren>();
if (includeThis) {
allChildren.Add(this);
}
if (m_Children != null) {
for (int i = 0; i < m_Children.Length; i++) {
allChildren.AddRange(m_Children[i].GetAllChildren(true));
}
}
return allChildren;
}
//Without allocation combination of count and getAt(index)
public int GetAllChildrenCount(bool includeThis = false)
{
var count = 0;
if (includeThis) { count++; }
for (int i = 0; i < m_Children.Length; i++) {
count += 1 + m_Children[i].GetAllChildrenCount();
}
return count;
}
public MyClassWithChildren GetAllChildrenAt(int index, bool includeThis = false)
{
if (includeThis) {
if (index == 0) { return this;}
index--;
}
for (int i = 0; i < m_Children.Length; i++) {
if (index == 0) { return m_Children[i]; }
index--;
var newIndex = index - m_Children[i].GetAllChildrenCount(false);
if (newIndex < 0) { return m_Children[i].GetAllChildrenAt(index); }
index = newIndex;
}
return null;
}
}
有谁知道更好的方法来做到这一点?一个简单的用例是搜索某个对象是否是另一个对象的子对象。另一种方法是找到所有具有特定属性值的孩子。
感谢您的时间
解决方案
也许这就是您正在寻找的:
public IEnumerable<MyClassWithChildren> GetAllChildren()
{
var items = new Queue<MyClassWithChildren>();
items.Enqueue(this);
while (items.TryDequeue(out var result))
{
yield return result;
for (var i = 0; i < result.m_children.Length; ++i) // use for instead of foreach to avoid enumerator creation
{
items.Enqueue(result.m_children[i]);
}
}
}
这将在外部循环处理它并请求下一个返回值之后评估返回值的子代。这意味着所有孩子都是惰性迭代的。如果您的外部循环将在第一个元素之后停止,则只有该元素已被排入结果队列。枚举数没有开销,m_children
因为此代码使用for
-loop 而不是foreach
-loop。
如果您需要所有元素的计数 - 只需使用 linq: GetAllChildren().Count()
。
推荐阅读
- typescript - 将 tsconfig 设置为忽略“类型 'bar' 上不存在属性 'foo'。” 但仅适用于特定变量
- python-3.x - 带有覆盆子的数据矩阵
- kotlin - JVM 使用 Java_xx 方法而不是 JavaCritical_xx
- ionic4 - 包含离子卡的 Ionic 4 离子载玻片 - 布局问题
- spring - 带有junit5的spring嵌入式kafka-引导服务器中没有给出可解析的引导URL
- mariadb - Mariadb mysql_upgrade 失败
- python - Python pandas在for循环中访问列名
- c# - 创建一个包含大量文件的虚拟文件夹
- python - imap 函数:传递一个列表和另一个固定字符串作为参数(Python 3.7/3.8)
- python - 获取自动发布到我在 Django 中开发应用程序的 URL 的数据的正确方法是什么?