I have one requirement to implement the extension method for List to find out the WhereNot. I am not suppose to use any existing Linq extension method like where etc.
For Example
IEnumerable<int> list = new List<int> {1,2,3,4,5,6};
var whereNotListInt = list.WhereNot((num) => num > 3));
foreach(int i in whereNotListInt)
{
Console.WriteLine(i);
}
Output:-
1
2
3
IEnumerable<string> list = new List<string> {"Cat", "Dog"};
var whereNotListStr = list.WhereNot((str) => str.StartsWith("D")));
foreach(string str in whereNotListStr )
{
Console.WriteLine(str);
}
Output: Cat
I tried below solution, but not able to figure out how to call the function.
public static class Utility
{
public static IEnumerable<T> WhereNot<T>(this IEnumerable<T> list, Func<T, bool> func)
{
foreach (var item in list)
{
yield return func(item);
}
}
}
Since you only want to return items for which the condition is not true, only return each item when func() returns false on that item.
public static class Utility
{
public static IEnumerable<T> WhereNot<T>(this IEnumerable<T> list, Func<T, bool> func)
{
foreach (var item in list)
{
if (!func(item))
yield return item;
}
}
}
So I've been scavenging the forums for a solution to this problem and I have this method for finding a node in a graph given a predicate:
public static class Extensions
{
public static IEnumerable<T> FindWhere<T>(this T root, Func<T, bool> predicate,
Func<T, IEnumerable<T>> getChildren)
where T : class
{
var stack = new Stack<T>();
stack.Push(root);
while (stack.Count != 0)
{
T item = stack.Pop();
if (item != null)
{
yield return item;
}
foreach (var child in getChildren(item))
stack.Push(child);
}
}
}
This should work most of the way, but how do I get the predicate into the method so that I can find any node in the graph that I wish to find? Any hints appreciated.
You can use a lambda expression like this:
myClass.FindWhere(x => x.HasSomeProperty, y => y.GetChildren())
Or you can declare methods with the right signature and pass those in.
bool IsOkay(MyClass mc) { ... }
IEnumerable<MyClass> GetChildren(MyClass mc) { ... }
...
myClass.FindWhere(IsOkay, GetChildren)
I want to manipulate all Controls within my form using a foreach loop, I currently am using the following method:
foreach (Control c in this.Controls)
{
ComponentResourceManager resourceManager = new ComponentResourceManager(typeof(Main));
resourceManager.ApplyResources(c, c.Name, new CultureInfo(lang));
}
The problem with this foreach, is that Controls within Containers aren't included.
How Can I include all the Controls within the Containers too?
I would like to do this in 1 or maybe 2 foreach loops.
Controls
Add the following class to your project:
public static class ControlExtensionMethods
{
public static IEnumerable<Control> GetOffsprings(this Control #this)
{
foreach (Control child in #this.Controls)
{
yield return child;
foreach (var offspring in GetOffsprings(child))
yield return offspring;
}
}
}
It will return all sub controls of the caller:
var offsprings = this.GetOffsprings();
You can use it in the loop:
foreach (Control c in this.GetOffsprings())
{
// Do action
}
Menu items
Add the following class to your project:
public static class MenuStripExtensionMethods
{
public static IEnumerable<ToolStripItem> GetSubItems(this ToolStrip #this)
{
foreach (ToolStripItem child in #this.Items)
{
yield return child;
foreach (var offspring in child.GetSubItems())
yield return offspring;
}
}
public static IEnumerable<ToolStripItem> GetSubItems(this ToolStripItem #this)
{
if (!(#this is ToolStripDropDownItem))
yield break;
foreach (ToolStripItem child in ((ToolStripDropDownItem) #this).DropDownItems)
{
yield return child;
foreach (var offspring in child.GetSubItems())
yield return offspring;
}
}
}
It will return all sub menu items of the caller:
var allMenuItems = this.menuStrip1.GetSubItems()
Make it recursive:
private static void ApplyResources(ComponentResourceManager resourceManager,
CultureInfo cultureInfo,
Control container)
{
foreach (var control in container.Controls)
{
resourceManager.ApplyResources(control, control.Name, cultureInfo);
ApplyResources(resourceManager, cultureInfo, control);
}
}
And use it like this:
var resourceManager = new ComponentResourceManager(typeof(Main));
var cultureInfo = new CultureInfo(lang);
ApplyResources(resourceManager, cultureInfo, this);
I have a custom method GetControlsOfType that looks like this:
public static List<TControl> GetControlsOfType<TControl>(this Control control) where TControl : Control
{
return (from n in control.Controls.Cast<Control>().Descendants(c => c.Controls.Cast<Control>())
where n is TControl
select (TControl)n).ToList();
}
It depends on this extension:
static public IEnumerable<T> Descendants<T>(this IEnumerable<T> source,
Func<T, IEnumerable<T>> DescendBy)
{
foreach (T value in source)
{
yield return value;
foreach (T child in DescendBy(value).Descendants<T>(DescendBy))
{
yield return child;
}
}
}
If I have a control structure like this (RadEditor is just a Telerik control for making rich text):
MyWebPage.aspx
- MyUserControl1.ascx
- MyRadEditor1
- MyUserControl2.ascx
- MyRadEditor2
If MyUserControl2.ascx calls the method below, I see both MyRadEditor1 and 2.
public static void SetRadEditors(this UserControl control, object entity)
{
control.GetControlsOfType<RadEditor>().ForEach(editor =>
{
// Should only show MyRadEditor2, but shows MyRadEditor1 and MyRadEditor2
});
}
Can anyone help me understand why this occurs?
Not sure right now (too tired to debug.. :-).
Anyway, try this:
public static IEnumerable<T> FindControlsRecursive<T>(this Control root)
{
foreach (Control child in root.Controls)
{
if (child is T)
{
yield return child;
}
if (child.Controls.Count > 0)
{
foreach (Control c in child.FindControlsRecursive<T>())
{
yield return c;
}
}
}
}
I have a tree created from this class.
class Node
{
public string Key { get; }
public List<Node> Children { get; }
}
I want to search in all children and all their children to get the ones matching a condition:
node.Key == SomeSpecialKey
How can I implement it?
It's a misconception that this requires recursion. It will require a stack or a queue and the easiest way is to implement it using recursion. For sake of completeness I'll provide a non-recursive answer.
static IEnumerable<Node> Descendants(this Node root)
{
var nodes = new Stack<Node>(new[] {root});
while (nodes.Any())
{
Node node = nodes.Pop();
yield return node;
foreach (var n in node.Children) nodes.Push(n);
}
}
Use this expression for example to use it:
root.Descendants().Where(node => node.Key == SomeSpecialKey)
If you want to maintain Linq like syntax, you can use a method to obtain all the descendants (children + children's children etc.)
static class NodeExtensions
{
public static IEnumerable<Node> Descendants(this Node node)
{
return node.Children.Concat(node.Children.SelectMany(n => n.Descendants()));
}
}
This enumerable can then be queried like any other using where or first or whatever.
Searching a Tree of Objects with Linq
public static class TreeToEnumerableEx
{
public static IEnumerable<T> AsDepthFirstEnumerable<T>(this T head, Func<T, IEnumerable<T>> childrenFunc)
{
yield return head;
foreach (var node in childrenFunc(head))
{
foreach (var child in AsDepthFirstEnumerable(node, childrenFunc))
{
yield return child;
}
}
}
public static IEnumerable<T> AsBreadthFirstEnumerable<T>(this T head, Func<T, IEnumerable<T>> childrenFunc)
{
yield return head;
var last = head;
foreach (var node in AsBreadthFirstEnumerable(head, childrenFunc))
{
foreach (var child in childrenFunc(node))
{
yield return child;
last = child;
}
if (last.Equals(node)) yield break;
}
}
}
You can try this extension method to enumerate the tree nodes:
static IEnumerable<Node> GetTreeNodes(this Node rootNode)
{
yield return rootNode;
foreach (var childNode in rootNode.Children)
{
foreach (var child in childNode.GetTreeNodes())
yield return child;
}
}
Then use that with a Where() clause:
var matchingNodes = rootNode.GetTreeNodes().Where(x => x.Key == SomeSpecialKey);
Why not use an IEnumerable<T> extension method
public static IEnumerable<TResult> SelectHierarchy<TResult>(this IEnumerable<TResult> source, Func<TResult, IEnumerable<TResult>> collectionSelector, Func<TResult, bool> predicate)
{
if (source == null)
{
yield break;
}
foreach (var item in source)
{
if (predicate(item))
{
yield return item;
}
var childResults = SelectHierarchy(collectionSelector(item), collectionSelector, predicate);
foreach (var childItem in childResults)
{
yield return childItem;
}
}
}
then just do this
var result = nodes.Children.SelectHierarchy(n => n.Children, n => n.Key.IndexOf(searchString) != -1);
Perhaps you need just
node.Children.Where(child => child.Key == SomeSpecialKey)
Or, if you need to search one level deeper,
node.Children.SelectMany(
child => child.Children.Where(child => child.Key == SomeSpecialKey))
If you need to search on all levels, take the following:
IEnumerable<Node> FlattenAndFilter(Node source)
{
List<Node> l = new List();
if (source.Key == SomeSpecialKey)
l.Add(source);
return
l.Concat(source.Children.SelectMany(child => FlattenAndFilter(child)));
}
public class Node
{
string key;
List<Node> children;
public Node(string key)
{
this.key = key;
children = new List<Node>();
}
public string Key { get { return key; } }
public List<Node> Children { get { return children; } }
public Node Find(Func<Node, bool> myFunc)
{
foreach (Node node in Children)
{
if (myFunc(node))
{
return node;
}
else
{
Node test = node.Find(myFunc);
if (test != null)
return test;
}
}
return null;
}
}
And then you can search like:
Node root = new Node("root");
Node child1 = new Node("child1");
Node child2 = new Node("child2");
Node child3 = new Node("child3");
Node child4 = new Node("child4");
Node child5 = new Node("child5");
Node child6 = new Node("child6");
root.Children.Add(child1);
root.Children.Add(child2);
child1.Children.Add(child3);
child2.Children.Add(child4);
child4.Children.Add(child5);
child5.Children.Add(child6);
Node test = root.Find(p => p.Key == "child6");
And just for fun (almost a decade later) an answer also using Generics but with a Stack and While loop, based off the accepted answer by #vidstige.
public static class TypeExtentions
{
public static IEnumerable<T> Descendants<T>(this T root, Func<T, IEnumerable<T>> selector)
{
var nodes = new Stack<T>(new[] { root });
while (nodes.Any())
{
T node = nodes.Pop();
yield return node;
foreach (var n in selector(node)) nodes.Push(n);
}
}
public static IEnumerable<T> Descendants<T>(this IEnumerable<T> encounter, Func<T, IEnumerable<T>> selector)
{
var nodes = new Stack<T>(encounter);
while (nodes.Any())
{
T node = nodes.Pop();
yield return node;
if (selector(node) != null)
foreach (var n in selector(node))
nodes.Push(n);
}
}
}
Given a collection one can use like this
var myNode = ListNodes.Descendants(x => x.Children).Where(x => x.Key == SomeKey);
or with a root object
var myNode = root.Descendants(x => x.Children).Where(x => x.Key == SomeKey);
A while back I wrote a codeproject article which describes how to use Linq to query tree-like structures:
http://www.codeproject.com/KB/linq/LinqToTree.aspx
This provides a linq-to-XML style API where you can search descendants, children, ancestors etc...
Probably overkill for your current problem, but might be of interest to others.
You can use this extension method to query the tree.
public static IEnumerable<Node> InTree(this Node treeNode)
{
yield return treeNode;
foreach (var childNode in treeNode.Children)
foreach (var flattendChild in InTree(childNode))
yield return flattendChild;
}
I have a generic extension method that can flatten any IEnumerable<T> and from that flattened collection, you can get the node you want.
public static IEnumerable<T> FlattenHierarchy<T>(this T node, Func<T, IEnumerable<T>> getChildEnumerator)
{
yield return node;
if (getChildEnumerator(node) != null)
{
foreach (var child in getChildEnumerator(node))
{
foreach (var childOrDescendant in child.FlattenHierarchy(getChildEnumerator))
{
yield return childOrDescendant;
}
}
}
}
Use this like this:
var q = from node in myTree.FlattenHierarchy(x => x.Children)
where node.Key == "MyKey"
select node;
var theNode = q.SingleOrDefault();
I use the following implementations for enumerating Tree items
public static IEnumerable<Node> DepthFirstUnfold(this Node root) =>
ObjectAsEnumerable(root).Concat(root.Children.SelectMany(DepthFirstUnfold));
public static IEnumerable<Node> BreadthFirstUnfold(this Node root) {
var queue = new Queue<IEnumerable<Node>>();
queue.Enqueue(ObjectAsEnumerable(root));
while (queue.Count != 0)
foreach (var node in queue.Dequeue()) {
yield return node;
queue.Enqueue(node.Children);
}
}
private static IEnumerable<T> ObjectAsEnumerable<T>(T obj) {
yield return obj;
}
BreadthFirstUnfold in implementation above uses queue of node sequences instead of nodes queue. This is not classic BFS algorithm way.