博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
自定义引用类型的Enumerable.Union调用(原创)
阅读量:4519 次
发布时间:2019-06-08

本文共 5060 字,大约阅读时间需要 16 分钟。

在开发的过程中常常会碰到一种需求,两个集合融合到一个集合里面,同时去除相同的成员。

说到这里,可能很多人脑中立刻就闪现了Union,Distinct之类的函数。的确,这两个函数可以解决大部分的问题。根据处理的对象的类型不同,实现需求的代码和原理都不一样。

1. 对象是系统自带的值类型。可以直接调用Union,即可实现上面的需求。

var x = new List
{ 1, 2, 3, 4, 5, 6 };var y = new List
{ 6, 7, 8, 9, 10 };var res = x.Union(y).ToList();//结果为{ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 }

2. 对象是系统自带的引用类型。由于对象为引用类型,在没有特殊处理的前提下,实际执行Union操作时,进行相同比较时的参照为对象的引用地址,表面上看起来是一样的,但是后台的引用地址不同,比较是否相同时就会返回‘不一样’。这种情况下,需要自定义一个实现了IEqualityComparer<T>的类作为参数传递进去

var x = new List
> { new List
() {
1}, new List
() {
2}, new List
() {
3} };var y = new List
> { new List
() { 3}, new List
() { 4}, new List
() { 5} };var res = x.Union(y).ToList();//结果Count为6

查看Union的函数,它有一个重载,Union(IEnumerable<TSource> second, IEqualityComparer<TSource> comparer)。也就是说我们可以自定义相同比较的规则。修改代码如下:

public Form2() {     InitializeComponent();     var x = new List
> {
new List
() {
1}, new List
() {
2}, new List
() {
3}}; var y = new List
> { new List
() { 3}, new List
() { 4}, new List
() { 5}}; var res = x.Union(y, new ListComparer
()).ToList();//结果Count为5 } class ListComparer
: IEqualityComparer
> { public bool Equals(List
x, List
y) { var except = x.Except(y); return except.Count() == 0 && x.Count == y.Count; } public int GetHashCode(List
obj) { return obj.Select(x => x.GetHashCode()).Aggregate((x, y) => x ^ y); } }

3. 对象是自定义的值类型自定义的值类型需要在定义过程中按照自己的需要重写Equals的方法。如果不重写也可以,在执行Union函数时,会调用系统的ValueType.Equals方法。只是这样就不一定是我们想要的结果了。贴上代码一目了然。在下面的TestB中,我要求只要ID相同,实例就是相同的。根据这个规则,最后的res.Count为4.

public Form2(){    InitializeComponent();    var x = new List
{
new TestB("One", "1"), new TestB("Two", "2"), new TestB("Three", "3")}; var y = new List
{
new TestB("One", "4"), new TestB("Two", "5"), new TestB("Six", "6")}; var res = x.Union(y).ToList();}struct TestB{ public string ID; public string Value; public TestB(string id, string value) { this.ID = id; this.Value = value; } public override string ToString() { return string.Format("{0}_{1}", ID, Value); } public override bool Equals(object obj) { if (obj is TestB) return this.ID.Equals(((TestB)obj).ID); else return false; }}

4. 对象是自定义的引用类型。综合以上三种情况的分析和实现方法,不难得出这种情况下有两种实现方法。

方法一:直接在自定义的过程中,重写GetHashCode和Equals函数;

public Form2(){    InitializeComponent();    var x = new List
{
new TestA("One", "1"), new TestA("Two", "2"), new TestA("Three", "3")}; var y = new List
{
new TestA("One", "1"), new TestA("Two", "5"), new TestA("Six", "6")}; var res = x.Union(y).ToList();}class TestA { public string ID; public string Value; public TestA(string id, string value) { this.ID = id; this.Value = value; } public override string ToString() { return string.Format("{0}_{1}", ID, Value); } public override bool Equals(object obj) { if (obj is TestA) return this.GetHashCode().Equals(((TestA)obj).GetHashCode()); else return false; } public override int GetHashCode() { int hashID = ID.GetHashCode(); int hashValue = Value.GetHashCode(); return hashID ^ hashValue; }}

方法二:另外定义一个类,实现IEqualityComparer<T>,作为相同的判断规则传入到Union函数中。

public Form2(){    InitializeComponent();    var x = new List
{ new TestA("One", "1"), new TestA("Two", "2"), new TestA("Three", "3") }; var y = new List
{ new TestA("One", "1"), new TestA("Two", "5"), new TestA("Six", "6") }; var res = x.Union(y, new TestAComparer()).ToList();}class TestA{ public string ID; public string Value; public TestA(string id, string value) { this.ID = id; this.Value = value; } public override string ToString() { return string.Format("{0}_{1}", ID, Value); }}class TestAComparer : IEqualityComparer
{ public bool Equals(TestA x, TestA y) { return GetHashCode(x).Equals(GetHashCode(y)); } public int GetHashCode(TestA obj) { int hashID = obj.ID.GetHashCode(); int hashValue = obj.Value.GetHashCode(); return hashID ^ hashValue; }}

留文备用。转载请注明出处:

转载于:https://www.cnblogs.com/icyJ/archive/2012/11/10/Union.html

你可能感兴趣的文章
ZOJ2833*(并查集)
查看>>
外连接简要总结
查看>>
第一次作业-准备篇
查看>>
【C++】继承时构造函数和析构函数
查看>>
shader一些语义或术语的解释
查看>>
opencv源代码之中的一个:cvboost.cpp
查看>>
Android通过泛型简化findViewById类型转换
查看>>
swift
查看>>
eclipse maven 插件的安装和配置
查看>>
mysql基本知识总结
查看>>
php的zend引擎执行过程 一
查看>>
pycharm 快捷键
查看>>
Linux常用命令
查看>>
AutoFac IoC DI 依赖注入
查看>>
.net中的设计模式---单例模式
查看>>
安装程序工具 (Installutil.exe)22
查看>>
python 学习(pip工具的安装)
查看>>
博客园在我的博客添加点击小心心特效
查看>>
如何简单解释 MapReduce算法
查看>>
微软Office Online服务安装部署(二)
查看>>