有没有办法简化这个反向枚举器?
Is there a way to simplify this reverse-enumerator?
我们有一个案例,我们有一个分层树结构,我们需要获得任何特定节点的 'branch'。该结构是一个从子到父的单向链表,但是我们想定义从父到子方向的分支。
这是我们提出的实施的过度简化示例。只是想知道是否有 better/more 有效的方法来实现这些限制。只是觉得这样做很冗长。
#nullable enable
public class Node {
public Node(String name, Node? parent)
=> (Name, Parent) = (name, parent);
public string Name { get; set; }
public Node? Parent { get; init; }
IEnumerable<Node> GetBranch(){
static IEnumerable<Node> getBranchReversed(Node? node) {
while (node is not null) {
yield return node;
node = node.Parent;
}
}
return getBranchReversed(this).Reverse();
}
}
我能想到的唯一其他方法是累积到一个列表中,然后插入到第一个位置,然后 return 列表(从我的记忆中输入这个所以它可能无法编译...)
ReadOnlyCollection<Node> GetBranch(){
Node? node = this;
var branch = new List<Node>();
while (node is not null) {
branch.insert(0, node);
node = node.Parent;
}
return branch.AsReadOnly();
}
再次,只是想知道是否有任何其他方法可以实现此目的。
总结评论
IEnumerable.Reverse 或多或少做了以下事情
var buffer = new List<int>(ienumerableToReverse);
for (int i = buffer.count - 1; i >= 0; --i)
yield return buffer.items[i];
需要注意的一点是,每次使用迭代器时它都会进行缓冲。它必须这样做,因为 IEnumerable 是惰性的。如果你想保持懒惰的行为,这就和你能做的一样好,无论你想使用什么解决方案,你都需要一个缓冲区。
如果你不想要懒惰的行为,我可能会自己做缓冲:
var branch = new List<Node>();
while (node is not null) {
branch.Add(node);
node = node.Parent;
}
branch.Reverse();
return branch;
这应该比您的示例更好,因为 Insert
需要为每个插入移动项目,从而导致二次缩放,而 .Reverse
是线性的。
我们有一个案例,我们有一个分层树结构,我们需要获得任何特定节点的 'branch'。该结构是一个从子到父的单向链表,但是我们想定义从父到子方向的分支。
这是我们提出的实施的过度简化示例。只是想知道是否有 better/more 有效的方法来实现这些限制。只是觉得这样做很冗长。
#nullable enable
public class Node {
public Node(String name, Node? parent)
=> (Name, Parent) = (name, parent);
public string Name { get; set; }
public Node? Parent { get; init; }
IEnumerable<Node> GetBranch(){
static IEnumerable<Node> getBranchReversed(Node? node) {
while (node is not null) {
yield return node;
node = node.Parent;
}
}
return getBranchReversed(this).Reverse();
}
}
我能想到的唯一其他方法是累积到一个列表中,然后插入到第一个位置,然后 return 列表(从我的记忆中输入这个所以它可能无法编译...)
ReadOnlyCollection<Node> GetBranch(){
Node? node = this;
var branch = new List<Node>();
while (node is not null) {
branch.insert(0, node);
node = node.Parent;
}
return branch.AsReadOnly();
}
再次,只是想知道是否有任何其他方法可以实现此目的。
总结评论
IEnumerable.Reverse 或多或少做了以下事情
var buffer = new List<int>(ienumerableToReverse);
for (int i = buffer.count - 1; i >= 0; --i)
yield return buffer.items[i];
需要注意的一点是,每次使用迭代器时它都会进行缓冲。它必须这样做,因为 IEnumerable 是惰性的。如果你想保持懒惰的行为,这就和你能做的一样好,无论你想使用什么解决方案,你都需要一个缓冲区。
如果你不想要懒惰的行为,我可能会自己做缓冲:
var branch = new List<Node>();
while (node is not null) {
branch.Add(node);
node = node.Parent;
}
branch.Reverse();
return branch;
这应该比您的示例更好,因为 Insert
需要为每个插入移动项目,从而导致二次缩放,而 .Reverse
是线性的。