zoukankan      html  css  js  c++  java
  • 一个简单的Linq to TreeNode

      最近两天写单元测试,碰到需要验证一个树是否是期望的,但是树这个结构要验证起来还真是有点烦。。。

      我的树大概是这样的:

     1 class TreeNode<T>
     2 {
     3         private static readonly TreeNode<T>[] Empty = new TreeNode<T>[0];
     4         public TreeNode() : this(default(T), Empty) { }
     5         public TreeNode(T value, IReadOnlyList<TreeNode<T>> children)
     6         {
     7             Value = value;
     8             Children = children;
     9         }
    10         public T Value { get; set; }
    11         public IReadOnlyList<TreeNode<T>> Children { get; set; }
    12 }
    View Code

      为了判等,这个树实现了IEquatable<TreeNode<T>>接口:

     1         public override bool Equals(object obj)
     2         {
     3             var other = obj as TreeNode<T>;
     4             if (other == null)
     5             {
     6                 return false;
     7             }
     8             return Equals(other);
     9         }
    10 
    11         public bool Equals(TreeNode<T> other)
    12         {
    13             return object.Equals(Value, other.Value) && Children.SequenceEqual(other.Children);
    14         }
    15 
    16         public override int GetHashCode()
    17         {
    18             return Value.GetHashCode() ^ Children.Aggregate(Children.Count, (seed, x) => seed ^ x.GetHashCode());
    19         }
    View Code

      看着还不错,不过由于T实际是个复杂类型,每次重写Equals也是个不轻松的事情,而且还要把整个期望的树给构造出来,呵呵,还是烦啊。。。

      但是,如果只需要判定个把简单属性,事情就方便了许多,所以,TreeNode需要一个方法来转换T的类型:

    1         public TreeNode<TResult> Select<TResult>(Func<T, TResult> selector)
    2         {
    3             return new TreeNode<TResult>(selector(Value), (from c in Children select c.Select(selector)).ToList());
    4         }
    View Code

      看起来不错,这样就可以有这样的code来玩转tree了:

    1 TreeNode<int> intTree = ...
    2 TreeNode<string> stringTree = intTree.Select(i => i.ToString());
    View Code

      等等,我们可以把这代码写的跟linq:

    1 TreeNode<int> intTree = ...
    2 TreeNode<string> stringTree = from i in intTree
    3                               select i.ToString();
    View Code

      测试代码继续啪啦啪啦的写,唉,测试失败了,什么情况,仔细一看,哦,tree下面节点的顺序错了,而tree的equals方法要求顺序,但是这个测试刚好不要求顺序,于是我有了两个选择:

    1. 改写equals方法 (不想折腾集合操作)

    2. 让节点排序 (对测试用例而言,构建一个有顺序的树可是很简单的事情)

      所以,我需要个OrderBy:

    1         public TreeNode<T> OrderBy<TKey>(Func<T, TKey> keySelector)
    2         {
    3             return new TreeNode<T>(Value, (from c in Children
    4                                            orderby keySelector(c.Value)
    5                                            select c.OrderBy(keySelector)).ToList());
    6         }
    View Code

      这下就可以随便折腾这个树了:

    1 TreeNode<int> intTree = ...
    2 TreeNode<string> stringTree = from i in intTree
    3                               let m = i % 3
    4                               order by m
    5                               select i.ToString();
    View Code
  • 相关阅读:
    Criteria和Detachedcriteria的区别及应用(转)
    Hibernate中DetachedCriteria的使用(转)
    jQuery的dom操作
    MyEclipse6.5安装SVN插件的三种方法(转)
    hibernate反向生成实体类
    PHP写文本日志
    关于微软ADO.NET提供的组件库里的UpdateDataSet()的用法心得
    比较文件内容是否一致
    在ListView的顶部和底部加入其他View
    Android中使用shape来定义控件的显示属性
  • 原文地址:https://www.cnblogs.com/vwxyzh/p/4044684.html
Copyright © 2011-2022 走看看