public static bool AllNodesChecked(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (!node.Checked)
{
return false;
}
AllNodesChecked(node.Nodes);
}
return true;
}
Test tree is
A1(checked) -> B1(unchecked)
A2(checked)
A3(checked)
but it isn't returning when it hits node B1.
EDIT: Thank you all for helping my tired brain. Recursion should only be attempted early in the day after a cold shower.
You are ignoring the return value of AllNodesChecked in the recursive call:
public static bool AllNodesChecked(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
if (!node.Checked || !AllNodesChecked(node.Nodes))
return false;
return true;
}
The return statement only returns from the current method in the call stack to the immediate caller. It doesn't suddenly return from all other calls above in the call stack.
Change:
AllNodesChecked(node.Nodes);
To:
if(!AllNodesChecked(node.Nodes))
return false;
I would take a slightly different approach here. What I'd do is I'd first write code that turns your tree (which I assume really is a tree, not an arbitrary graph) into a sequence of nodes. Something like:
static IEnumerable<Node> AllNodes(this Node node)
{
var stack = new Stack<Node>();
stack.Push(node);
while(stack.Count > 0)
{
var current = stack.Pop();
yield return current;
foreach(var child in current.Nodes)
stack.Push(child);
}
}
and now you can use sequence operators:
bool allChecked = root.AllNodes().All(x=>x.Checked);
No recursion, no problem.
You're not evaluating the result of the recursive call to check child nodes.
Try this:
public static bool AllNodesChecked(TreeNodeCollection nodes)
{
foreach (TreeNode node in nodes)
{
if (node.Checked == false || !AllNodesChecked(node.Nodes))
{
return false;
}
}
return true;
}
I have to add my two cents.... Learn to functional programming IMHO.
public static bool AllNodesChecked(TreeNodeCollection nodes)
{
return nodes.All(i => i.Checked && AllNodesChecked(i.Nodes));
}
Related
I have this method that yields the values yielded by 2 methods:
private IEnumerable<Node> ParseEmptyElement()
{
foreach (var node in ParseMembersOfObject())
{
yield return node;
}
foreach (var node in ParseNestedProperty())
{
yield return node;
}
}
It seems very verbose for me.
Is there a better way express "yield all values from MethodX" and after that, do the same for MethodY?
Example:
private IEnumerable<Node> ParseEmptyElement()
{
#yield all# items from ParseMembersOfObject();
#yield all# items from ParseNestedProperty();
}
I don't want to be force to write the foreach loops into a single line! but I also don't want to write fully-fledged foreach loops with curly braces and all the stuff :)
As Marc commented, this is equivalent:
private IEnumerable<Node> ParseEmptyElement()
{
return ParseMembersOfObject().Concat(ParseNestedProperty());
}
Concat is implemented using deferred execution, so this will not evaluate your enumerables early.
Incidentally, Concat is implemented with the foreach loops on a single line:
static IEnumerable<TSource> ConcatIterator<TSource>(IEnumerable<TSource> first,
IEnumerable<TSource> second) {
foreach (TSource element in first) yield return element;
foreach (TSource element in second) yield return element;
}
If you don't like Concat, and you still want braces, you could still keep them and just format your code more concisely:
private IEnumerable<Node> ParseEmptyElement()
{
foreach (var node in ParseMembersOfObject()) { yield return node; }
foreach (var node in ParseNestedProperty()) { yield return node; }
}
I have a treeview list check boxes and the list contains nodes, subnodes and in some cases subnode of subnode. When user check some items i want to get list of selected items.
On this why I get only selcted items of main node:
foreach (System.Windows.Forms.TreeNode aNode in tvSastavnica.Nodes)
{
if (aNode.Checked == true)
{
Console.WriteLine(aNode.Text);
}
}
How to travers through whole treeview and get checked items in subnodes?
If you like LINQ, you can create an extension method that traverses the whole treeview:
internal static IEnumerable<TreeNode> Descendants(this TreeNodeCollection c)
{
foreach (var node in c.OfType<TreeNode>())
{
yield return node;
foreach (var child in node.Nodes.Descendants())
{
yield return child;
}
}
}
Then you can perform every operations you want using LINQ. In your case, getting a list of selected nodes is easy:
var selectedNodes = myTreeView.Nodes.Descendants()
.Where(n => n.Checked)
.Select(n => n.Text)
.ToList();
An advantage of this approach is it is generic.
However, because the Descendant() method traverses the whole tree, it might be a bit less efficient than the answer given by #mybirthname because it only cares about nodes that are checked with their parents. I dont known if your use case includes this constraint.
EDIT: Now #mybirthname answer has been edited, it is doing the same. Now you have the loop and the LINQ solution, both are recursive.
public void GetCheckedNodes(TreeNodeCollection nodes)
{
foreach(System.Windows.Forms.TreeNode aNode in nodes)
{
//edit
if(!aNode.Checked)
continue;
Console.WriteLine(aNode.Text);
if(aNode.Nodes.Count != 0)
GetCheckedNodes(aNode.Nodes);
}
}
You don't make look back into the child notes, using recursion you can do it.
You need method like this ! In your code just call once GetCheckedNodes(tvSastavnica.Nodes) and all checked nodes should be displayed !
my way:
void LookupChecks(TreeNodeCollection nodes, List<TreeNode> list)
{
foreach (TreeNode node in nodes)
{
if (node.Checked)
list.Add(node);
LookupChecks(node.Nodes, list);
}
}
useage:
var list = new List<TreeNode>();
LookupChecks(TreeView.Nodes, list);
Say rootNode is a multi-hierarchy data structure.
rootNode.Add(node1);
rootNode.Add(node2);
node1.Add(node3);
node1.Add(node4);
node3.Add(node5);
If use foreach to traverse rootNode will only get node1, node2. How do I traverse all nodes in rootNode?
foreach(var node in rootNode){...}
You can traverse the tree using recursion.
VisitNode(Node n){
foreach(var cn in n.Children){
VisitNode(cn);
}
//Do what you want to do with your node here
Console.Writeline(n.Value);
}
Here is an example of breadth first traversal.
Make a recursive call:
TraverseNodes(parentNode)
{
for each (Node node in parentNode)
{
if (node.Nodes.Count>0)
TraverseNodes(node);
}
}
You can setup a simple recursive function
//Pseudo-code
public void traverse(Node n)
{
if(n hasChildren)
{
foreach(Node child in n.children)
{
traverse(child);
}
}
}
The easiest way would be recursion. What is recursion? See this answer for an example.
public void TraverseNodes(Node parentNode)
{
//iterate through child nodes
foreach(var node in parentNode)
{
//action
//iterate though child's child nodes.
TraverseNodes(node);
}
}
Basically you are performing the same operation on all the child items by calling the same method (TraverseNodes) on all of the parent items (starting from the first parent).
If your structure isn't too deep then you can safely use the recursive method given in the other answers.
If, however, your structure is potentially very deep then using recursion runs the risk of blowing the call stack and causing a StackOverflowException.
Here's an example of a non-recursive way of traversing your structure:
var stack = new Stack<TNode>();
stack.Push(rootNode);
while (stack.Count > 0)
{
var node = stack.Pop();
// do whatever you need to do with each node here
foreach (var childNode in node)
{
stack.Push(childNode);
}
}
Even if the (working) recursive methods have been posted yet, I'd like to contribute two additional methods.
The first one "pushes" each node in the tree into an Action<Node> that can "consume" it.
public void TraverseWithAction(Action<Node> nodeAction) {
nodeAction(this);
foreach(Node n in this.children) {
n.TraverseWithAction(nodeAction);
}
}
Usage example:
rootNode.TraverseWithAction(n => buffer.Append(n.ToString()));
The second one provides an IEnumerable<Node> over the root node and all its child nodes, recursively. (And, yes, there are only two loops but they can handle trees deeper than two.)
public IEnumerable<Node> TraverseAsEnumerable() {
yield return this;
foreach(Node n in this.children) {
foreach (Node n2 in n.TraverseAsEnumerable()) {
yield return n2;
}
}
}
Usage example:
foreach (Node n in rootNode.TraverseAsEnumerable()) {
// do something with n
}
Both methods use recursion so they might fail on very deep structures.
I need to iterate through a LinkedList<T> (in .NET 2.0) and remove all the items according to a given criteria.
It was easy way under Java, since I could do the following:
Iterator<E> i = list.iterator();
while (i.hasNext()) {
E e = i.next();
if (e == x) {
// Found, so move it to the front,
i.remove();
list.addFirst(x);
// Return it
return x;
}
}
Unfortunately, in the .NET behavior of IEnumerator<T> (the equivalent of Iterator<E>) there's no remove method to remove the current element from the collection.
Also, in the LinkedList<T> there's no way to access an element at a given index, to accomplish the task by iterating back from the last to the first.
Have you got any idea on how to do it? Thank you very much!
This will remove all nodes that match a criteria, in one loop through the linked list.
LinkedListNode<E> node = list.First;
while (node != null)
{
var next = node.Next;
if (node.Value == x) {
list.Remove(e);
}
node = next;
}
I believe that's what you're attempting... You also added back in the node at the beginning of the list (so your java code didn't remove all of the nodes, but rather moved the first matching to the beginning of the list). That would be easy to do with this approach, as well.
It's actually a lot easier in C#.
function PlaceAtHead(<T> x)
{
list.Remove(x);
list.AddFirst(x);
return x;
}
One ugly option is to iterate through your list, find all the items that apply and store them in a list. Then iterate through your second list and call remove on your LinkedList...
I'm hoping someone else has a more elegant solution :)
Just a little addition to Reed Copsey's answer with a predicate:
public static T MoveAheadAndReturn<T>(LinkedList<T> ll, Predicate<T> pred)
{
if (ll == null)
throw new ArgumentNullException("ll");
if (pred == null)
throw new ArgumentNullException("pred");
LinkedListNode<T> node = ll.First;
T value = default(T);
while (node != null)
{
value = node.Value;
if (pred(value))
{
ll.Remove(node);
ll.AddFirst(node);
break;
}
node = node.Next;
}
return value;
}
I need to write a tree search method which takes a type parameter T and returns all items of type T that exist in the tree. Is there any way to do this? I would prefer elegance over efficiency at this point...
Something like this:
internal static IEnumerable<T> AllDescendantNodes<T>( this TreeNode input )
where T class;
{
T current = null;
foreach ( TreeNode node in input.Nodes )
if( (current = node as T) != null )
{
yield return current;
foreach ( var subnode in node.AllDescendantNodes<T>() )
yield return subnode;
}
}
You would then call this against the root node as an extension method:
foreach( MyCustomNodeClass item in rootNode.AllDescendantNodes<MyCustomNodeClass>() )
{
...
}
Well, internally the method would have to iterate over all the elements of the tree, so the skip to just enumerating over it, and using the OfType LINQ method isn't that far:
var onlyTs = yourTree.OfType<SomeT>();
Assuming your tree is generic. i.e. Item<T>.
int count = yourTree.Count(p => p == typeof(T));
Otherwise, parse each node and compare "item == typeof(T)"
What you need is a basic tree traversal function (preorder, inorder or postorder -- this doesn't matter) and a filter function. Then you can compose those two together and get what you need:
IEnumerable<T> Traverse(Tree<T> tree)
{
yield return tree.Data;
foreach(Tree<T> subtree in tree.Subtrees)
foreach(T t in Traverse(subtree))
yield return t;
}
IEnumerable<U> Filter<T, U>(IEnumerable<T> source)
where U : T
{
foreach(T t in source)
if(t is U)
yield return (U)t;
}