使用 yield return 递归获取树结构的子节点
Get children of a Tree-Structure recursively by using yield return
我想获得树状结构中所有成员的列表(一个包含 n 个组的组,其中包含 n 个组等等。根元素也包含成员。
架构:
Group
Group
Member
Member
Member
Group
Member
Group
Member
Member
Group
Group
Group
Member
现在我的代码如下所示:
public IEnumerable<Member> GetMembers() {
foreach(var member in this.MemberCollection) {
yield return member;
}
foreach(var group in this.GroupCollection) {
GetMembers();
}
}
不幸的是,这不起作用 - "GetMembers()" 调用刚刚得到 "ignored" - 有 "Workaround" 吗?
我已经找到了与此类似的解决方案:
public IEnumerable<Member> GetMembers() {
foreach(var group in this.GroupCollection) {
foreach(var member in GetMembers()) {
yield return member;
}
}
}
简单地调用GetMembers
不会return调用方法的结果,如果它没有被枚举(并且它使用yield
),它不会出现被调用,而不是你可以做这样的事情:
public IEnumerable<Member> GetMembers() {
foreach(var member in this.MemberCollection) {
yield return member;
}
foreach(var group in this.GroupCollection) {
foreach(var member in group.GetMembers()) {
yield return member;
}
}
}
当您在方法中使用 yield
时,编译器实际上会生成一个单独的 class 来实现 IEnumerable<>
到 return 您的结果 - class只懒惰地枚举,所以如果你实际上没有迭代结果,它们就不会被评估(并且也不会评估 直到 你枚举它们,如果你依赖 属性 可能在其他地方发生突变)
要递归,你的方法应该带一个参数(否则递归将永远不会停止):
public IEnumerable<Member> GetMembers(Group group) {
foreach(var member in group.MemberCollection) {
yield return member;
}
foreach(var subGroup in group.GroupCollection) {
foreach (var member in GetMembers(group)) {
yield return member;
}
}
}
但是,递归迭代器块对于深度嵌套的层次结构往往效率很低。更好的方法是使用迭代而不是递归。要像递归方法一样获得深度优先遍历,您可以这样做:
public IEnumerable<Member> GetMembers() {
var stack = new Stack<Group>();
stack.Push(this);
while (stack.Count > 0) {
var group = stack.Pop();
foreach(var member in group.MemberCollection) {
yield return member;
}
foreach(var subGroup in group.GroupCollection) {
stack.Push(subGroup);
}
}
}
要获得广度优先遍历,请使用队列而不是堆栈。
我想获得树状结构中所有成员的列表(一个包含 n 个组的组,其中包含 n 个组等等。根元素也包含成员。
架构:
Group
Group
Member
Member
Member
Group
Member
Group
Member
Member
Group
Group
Group
Member
现在我的代码如下所示:
public IEnumerable<Member> GetMembers() {
foreach(var member in this.MemberCollection) {
yield return member;
}
foreach(var group in this.GroupCollection) {
GetMembers();
}
}
不幸的是,这不起作用 - "GetMembers()" 调用刚刚得到 "ignored" - 有 "Workaround" 吗?
我已经找到了与此类似的解决方案:
public IEnumerable<Member> GetMembers() {
foreach(var group in this.GroupCollection) {
foreach(var member in GetMembers()) {
yield return member;
}
}
}
简单地调用GetMembers
不会return调用方法的结果,如果它没有被枚举(并且它使用yield
),它不会出现被调用,而不是你可以做这样的事情:
public IEnumerable<Member> GetMembers() {
foreach(var member in this.MemberCollection) {
yield return member;
}
foreach(var group in this.GroupCollection) {
foreach(var member in group.GetMembers()) {
yield return member;
}
}
}
当您在方法中使用 yield
时,编译器实际上会生成一个单独的 class 来实现 IEnumerable<>
到 return 您的结果 - class只懒惰地枚举,所以如果你实际上没有迭代结果,它们就不会被评估(并且也不会评估 直到 你枚举它们,如果你依赖 属性 可能在其他地方发生突变)
要递归,你的方法应该带一个参数(否则递归将永远不会停止):
public IEnumerable<Member> GetMembers(Group group) {
foreach(var member in group.MemberCollection) {
yield return member;
}
foreach(var subGroup in group.GroupCollection) {
foreach (var member in GetMembers(group)) {
yield return member;
}
}
}
但是,递归迭代器块对于深度嵌套的层次结构往往效率很低。更好的方法是使用迭代而不是递归。要像递归方法一样获得深度优先遍历,您可以这样做:
public IEnumerable<Member> GetMembers() {
var stack = new Stack<Group>();
stack.Push(this);
while (stack.Count > 0) {
var group = stack.Pop();
foreach(var member in group.MemberCollection) {
yield return member;
}
foreach(var subGroup in group.GroupCollection) {
stack.Push(subGroup);
}
}
}
要获得广度优先遍历,请使用队列而不是堆栈。