惯性聚合 高效追踪和阅读你感兴趣的博客、新闻、科技资讯
阅读原文 在惯性聚合中打开

推荐订阅源

N
Netflix TechBlog - Medium
V
Vulnerabilities – Threatpost
Google Online Security Blog
Google Online Security Blog
Hugging Face - Blog
Hugging Face - Blog
L
LINUX DO - 热门话题
云风的 BLOG
云风的 BLOG
P
Proofpoint News Feed
D
Docker
C
Cyber Attacks, Cyber Crime and Cyber Security
MyScale Blog
MyScale Blog
P
Palo Alto Networks Blog
T
Tenable Blog
P
Privacy International News Feed
Google DeepMind News
Google DeepMind News
小众软件
小众软件
Cisco Talos Blog
Cisco Talos Blog
aimingoo的专栏
aimingoo的专栏
Cyber Security Advisories - MS-ISAC
Cyber Security Advisories - MS-ISAC
A
Arctic Wolf
C
Cybersecurity and Infrastructure Security Agency CISA
C
Cisco Blogs
T
Threat Research - Cisco Blogs
NISL@THU
NISL@THU
The Hacker News
The Hacker News
Project Zero
Project Zero
AWS News Blog
AWS News Blog
Simon Willison's Weblog
Simon Willison's Weblog
cs.CL updates on arXiv.org
cs.CL updates on arXiv.org
T
Threatpost
V
Visual Studio Blog
The GitHub Blog
The GitHub Blog
The Cloudflare Blog
Last Week in AI
Last Week in AI
Jina AI
Jina AI
Cyberwarzone
Cyberwarzone
The Register - Security
The Register - Security
C
CXSECURITY Database RSS Feed - CXSecurity.com
Vercel News
Vercel News
D
Darknet – Hacking Tools, Hacker News & Cyber Security
MongoDB | Blog
MongoDB | Blog
U
Unit 42
Scott Helme
Scott Helme
A
About on SuperTechFans
WordPress大学
WordPress大学
F
Fortinet All Blogs
大猫的无限游戏
大猫的无限游戏
G
GRAHAM CLULEY
Latest news
Latest news
让小产品的独立变现更简单 - ezindie.com
让小产品的独立变现更简单 - ezindie.com
S
Schneier on Security

博客园 - Zhenway

Azure SignalR支持replication啦 Azure SignalR总览 定制json序列化 今天折腾这么一个正则 docfx组件介绍--YamlSerialization docfx daylybuild docfx开源啦 docfx组件介绍--MarkdownLite docfx预热中 合并批量请求 在finally中调用一个需要await的方法 当泛型方法推断,扩展方法遇到泛型类型in/out时。。。 4.5你太黑了,不带这么玩TypeForwardedTo的 一个非常简单的反射加速方案 加载时预防并发执行 又发现一个msdn的坑 又发现个.net framework的坑 sql server死锁神器 踩到一个Emit的坑,留个纪念
一个简单的Linq to TreeNode
Zhenway · 2014-10-22 · via 博客园 - Zhenway

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

  我的树大概是这样的:

 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