class TreeNode
{
public string Value { get; set;}
public Collection<TreeNode> Nodes { get; set;}
public TreeNode()
{
Nodes = new Collection<TreeNode>();
}
}
1)如何编写递归lambda表达式以返回具有特定值的TreeNode(如果未找到则返回null),假设值是唯一的?当然#1可以使用#2来回答,但我想如果你知道没有重复,可能会有一种更有效的方法。
2)假设值不是唯一的,现在返回匹配列表?
答案 0 :(得分:6)
编辑:更正了代码,我确实编译并测试了两段代码,但在修复VS之前我必须先粘贴版本。对不起。
我添加了一个带有代码的Subversion存储库,包括单元测试,以确保它现在按预期工作,是here,使用用户名和密码登录为“guest”,没有报价。
像这样:
1 :先找
Func<TreeNode, String, TreeNode> findNode = null; // satisfy recursion re-use
findNode = (n, value) =>
{
if (n == null) return n;
if (n.Value == value) return n;
foreach (var subNode in n.Nodes)
{
TreeNode foundNode = findNode(subNode, value);
if (foundNode != null) return foundNode;
}
return null;
};
请注意,此处的陷阱是对于要递归的lambda或委托,在将实际委托分配给变量之前,需要先使用已知值声明变量。否则,编译器会在给定值之前抱怨您正在使用变量。
2 :全部找到
Func<TreeNode, String, List<TreeNode>> findNodes = null;
findNodes = (n, value) =>
{
var result = new List<TreeNode>();
if (n == null) return result;
if (n.Value == value) result.Add(n);
foreach (var subNode in n.Nodes)
{
result.AddRange(findNodes(subNode, value));
}
return result;
};
这里的诀窍就是收集每个级别的节点,并向上聚合。
答案 1 :(得分:0)
这个怎么样..
public class Node<T> where T:IComparable
{
public T Value { get; set; }
public IList<Node<T>> Children { get; set; }
public override string ToString()
{
return Value.ToString();
}
public static Func<T, Node<T>, Node<T>> GetFindFirstFunc()
{
Func<T, Node<T>,Node<T>> func = null;
func = (value,currentNode) =>
{
if (currentNode.Value.CompareTo(value) == 0)
{
return currentNode;
}
if (currentNode.Children != null)
{
foreach (var child in currentNode.Children)
{
var result = func(value, child);
if (result != null)
{
//found the first match, pass that out as the return value as the call stack unwinds
return result;
}
}
}
return null;
};
return func;
}
public static Func<T, Node<T>, IEnumerable<Node<T>>> GetFindAllFunc()
{
Func<T, Node<T>, IEnumerable<Node<T>>> func = null;
List<Node<T>> matches = new List<Node<T>>();
func = (value, currentNode) =>
{
//capture the matches List<Node<T>> in a closure so that we don't re-create it recursively every time.
if (currentNode.Value.CompareTo(value) == 0)
{
matches.Add(currentNode);
}
if (currentNode.Children != null)
{
//process all nodes
foreach (var child in currentNode.Children)
{
func(value, child);
}
}
return matches;
};
return func;
}
}
这是调用代码:
static void Main(string[] args)
{
Node<int> rootNode = new Node<int>
{
Value = 1,
Children = new List<Node<int>>
{
new Node<int>
{ Value = 2,
Children = new List<Node<int>>
{
new Node<int>{ Value = 7},
new Node<int>{ Value = 4}
}
},
new Node<int>
{ Value = 5,
Children = new List<Node<int>>
{
new Node<int>{ Value = 6},
new Node<int>{ Value = 7}
}
}
}
};
Func<int, Node<int>, Node<int>> findFirst = Node<int>.GetFindFirstFunc();
var firstValue = findFirst(7, rootNode);
Func<int, Node<int>, IEnumerable<Node<int>>> findAll = Node<int>.GetFindAllFunc();
var allvalues = findAll(7, rootNode);
}