.NET/C#中对自定义对象集合进行自定义排序的方法
一个集合可否排序,要看系统知不知道排序的规则,像内建的系统类型,int ,string,short,decimal这些,系统知道怎么排序,而如果一个集合里面放置的是自定义类型,比如自己定义了一个Car类型,要把它排序,系统是不知道怎么办的。
那么,如何告知系统排序的规则呢?有以下几种方法:
1:对类实现IComparable接口,示例如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace 对集合对象进行排序
- {
- class Product : IComparable
- {
- public string Name
- {
- get;
- private set;
- }
- public decimal Price
- {
- get;
- private set;
- }
- public Product(string name, decimal price)
- {
- Name = name;
- Price = price;
- }
- public Product()
- {
- }
- public static List<Product> GetSampleProduct()
- {
- return new List<Product>
- {
- new Product { Name = "Watch", Price = 12345.56m },
- new Product { Name = "Knife", Price = 224.50m },
- new Product { Name = "EZpe", Price = 12.50m },
- new Product { Name = "ETorch", Price = 58.5m } };
- }
- public override string ToString()
- {
- return string.Format("{0} : {1}", Name, Price);
- }
- int IComparable.CompareTo(object obj)
- {
- Product temp = (Product)obj;
- return this.Name.CompareTo(temp.Name);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- List<Product> ProductSample = Product.GetSampleProduct();
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- Console.WriteLine();
- ProductSample.Sort();
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- Console.ReadKey();
- }
- }
- }
其中最主要的是这句:
class Product :IComparable
跟这句:
int IComparable.CompareTo(object obj)
{
Product temp = (Product)obj;
return this.Name.CompareTo(temp.Name);
}
就是实现了IComparable.CompareTo()这个方法。然后就可以直接调用 SomeProductList.Sort();方法来进行排序。
2,指定IComparer 类的对象。
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace SortTeset2
- {
- class Product
- {
- public string Name
- {
- get;
- private set;
- }
- public decimal Price
- {
- get;
- private set;
- }
- public Product(string name, decimal price)
- {
- Name = name;
- Price = price;
- }
- public Product()
- {
- }
- public static List<Product> GetSampleProduct()
- {
- return new List<Product>
- {
- new Product { Name = "Watch", Price = 12345.56m },
- new Product { Name = "Knife", Price = 224.50m },
- new Product { Name = "Rope", Price = 12.50m },
- new Product { Name = "ETorch", Price = 58.5m }
- };
- }
- public override string ToString()
- {
- return string.Format("{0} : {1}", Name, Price);
- }
- }
- class ProductNameComparer : IComparer<Product>
- {
- public int Compare(Product first, Product second)
- {
- return first.Name.CompareTo(second.Name);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- List<Product> ProductSample = Product.GetSampleProduct();
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- Console.WriteLine();
- ProductSample.Sort(new ProductNameComparer());
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- }
- }
- }
这儿我们新定义了一个类:ProductNameComparer,这个类实现了泛型接口:IComparer<Product>,然后在
ProductSample.Sort(new ProductNameComparer());
语句中我们提供了一个比较器对象。
这种方法看上去不如直接实现ICompareable接口来得简洁。
这种方法可以用匿名方法进行改进:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace SortTeset3
- {
- class Product
- {
- public string Name
- {
- get;
- private set;
- }
- public decimal Price
- {
- get;
- private set;
- }
- public Product(string name, decimal price)
- {
- Name = name;
- Price = price;
- }
- public Product()
- {
- }
- public static List<Product> GetSampleProduct()
- {
- return new List<Product>
- {
- new Product { Name = "Watch", Price = 12345.56m },
- new Product { Name = "Knife", Price = 224.50m },
- new Product { Name = "Rope", Price = 12.50m },
- new Product { Name = "ETorch", Price = 58.5m }
- };
- }
- public override string ToString()
- {
- return string.Format("{0} : {1}", Name, Price);
- }
- }
- class Program
- {
- static void Main(string[] args)
- {
- List<Product> ProductSample = Product.GetSampleProduct();
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- Console.WriteLine();
- ProductSample.Sort(delegate(Product first, Product second)
- {
- return first.Name.CompareTo(second.Name);
- });
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- }
- }
- }
这一次,不用定义那个类,然后使用它的方法了,而是直接填充delegate接口。
这种方法还可以进一步用Lambda表达式改进,如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace SortTeset3
- {
- class Product
- {
- public string Name
- {
- get;
- private set;
- }
- public decimal Price
- {
- get;
- private set;
- }
- public Product(string name, decimal price)
- {
- Name = name;
- Price = price;
- }
- public Product()
- {
- }
- public static List<Product> GetSampleProduct()
- {
- return new List<Product>
- {
- new Product { Name = "Watch", Price = 12345.56m },
- new Product { Name = "Knife", Price = 224.50m },
- new Product { Name = "Rope", Price = 12.50m },
- new Product { Name = "ETorch", Price = 58.5m }
- };
- }
- public override string ToString()
- {
- return string.Format("{0} : {1}", Name, Price);
- }
- }
- class Program39
- {
- static void Main(string[] args)
- {
- List<Product> ProductSample = Product.GetSampleProduct();
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- Console.WriteLine();
- ProductSample.Sort((first, second) => first.Name.CompareTo(second.Name));
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- }
- }
- }
变态的是,还可以进一步改进,使用扩展方法,如下:
- using System;
- using System.Collections.Generic;
- using System.Linq;
- using System.Text;
- namespace SortTeset3
- {
- class Product
- {
- public string Name
- {
- get;
- private set;
- }
- public decimal Price
- {
- get;
- private set;
- }
- public Product(string name, decimal price)
- {
- Name = name;
- Price = price;
- }
- public Product()
- {
- }
- public static List<Product> GetSampleProduct()
- {
- return new List<Product>
- {
- new Product { Name = "Watch", Price = 12345.56m },
- new Product { Name = "Knife", Price = 224.50m },
- new Product { Name = "Rope", Price = 12.50m },
- new Product { Name = "ETorch", Price = 58.5m }
- };
- }
- public override string ToString()
- {
- return string.Format("{0} : {1}", Name, Price);
- }
- }
- class Program39
- {
- static void Main(string[] args)
- {
- List<Product> ProductSample = Product.GetSampleProduct();
- foreach(Product tmp in ProductSample)
- {
- Console.WriteLine(tmp);
- }
- Console.WriteLine();
- foreach(Product tmp in ProductSample.OrderBy(p => p.Name))
- {
- Console.WriteLine(tmp);
- }
- }
- }
- }
“这里似乎调用了一个OrderBy方法,但查阅一下MSDN,就会发现这个方法在List<Product>中根本不存在。之所以能调用它,是由于存在一个扩展方法。这里实际不再是"原地"对列表进行排序,而只是按特定的顺序获取列表的内容。有的时候,你需要更改实际的列表;但有的时候,没有任何副作用的排序显得更"善解人意"。重点在于,现在的写法更简洁,可读性更好(当然是在你理解了语法之后)。我们的想法是"列表按名称排序",现在的代码正是这样做的。并不是"列表通过将一个产品的名称与另一个产品的名称进行比较来排序",就像C# 2代码所做的那样。也不是使用知道如何将一个产品与另一个产品进行比较的另一个类型的实例来按名称排序。这种简化的表达方式是C# 3的核心优势之一。既然单独的数据查询和操作是如此的简单,那么在执行更大规模的数据处理时,仍然可以保持代码的简洁性和可读性,这进而鼓励开发者以一种"以数据为中心"的方式来观察世界。”
最后这两步的语法,绝对是一个会用其它语言比如C/C++,VB的人所无法明白的,C#进化速度真是快。。。。。。。
关于排序,暂时还不知道有没有其它的方法,日后再补记。
参考书籍:《C#与.NET3.5高级程序设计》,《深入解析C#》(C# in depth) 。
另外,这篇文章还提到了另外两种更深入的做法:1,自定义排序,可以提供一个接口,接受一个排序指标,然后对指定List进行排序,2,用LINQ的orderby子句实现排序。
“
以自定义方式可以实现的更多的控制,例如我们重构BookComparison: // Release : code01, 2009/04/12 // Author : Anytao, http://www.anytao.com/ // List : BookComparison.cs public class BookComparison : IComparer<Book>{ privateComparisonType type; publicBookComparison(ComparisonType type) { this.type = type; } publicintCompare(Book x, Book y) { switch(this.type) { caseComparisonType.Price: returnx.Price.CompareTo(y.Price); break; caseComparisonType.PublishDate: returnx.PublishDate.CompareTo(y.PublishDate); break; default: break; } return0; } } 添加一个ComparisonType结构,在BookComparson初始化时决定Comparison的方式: //04 Sort by custom comparison: BookComparison bs.Books.Sort(newBookComparison(ComparisonType.PublishDate).Compare); 结论 自定义Comparison为实现更好的Sort控制,提供了很好的扩展机制。在我们的实际应用中,对于例如BookStore这样的具体应用而言,我更推荐以LINQ的OrderBy来实现,例如: //05 Sort by Linq var list = from c inbs.Books orderby c.PublishDate ascending select c; foreach(var item inlist) { Console.WriteLine(string.Format("{0}:{1}, {2}", item.Name, item.Price, item.PublishDate.ToString())); } orderby子句可以选择任意的排序条件,同时ascending或者descending控制升序和降序。 |
.NET/C#中对自定义对象集合进行自定义排序的方法的更多相关文章
- C#中对象,字符串,dataTable、DataReader、DataSet,对象集合转换成Json字符串方法。
C#中对象,字符串,dataTable.DataReader.DataSet,对象集合转换成Json字符串方法. public class ConvertJson { #region 私有方法 /// ...
- JAVA 自定义对象集合 List<T> 根据自定义字段去重
1.拥有自定义对象 MyUser @Data public class MyUser { private String userName; private String passWord; } 2.编 ...
- C#高级知识点概要(3) - 特性、自动属性、对象集合初始化器、扩展方法、Lambda表达式和Linq查询
1.特性(Attributes) 特性(Attributes),MSDN的定义是:公共语言运行时允许你添加类似关键字的描述声明,叫做attributes, 它对程序中的元素进行标注,如类型.字段.方法 ...
- nuxtjs在vue组件中使用window对象编译报错的解决方法
我们知道nuxtjs是做服务端渲染的,他有很多声明周期是运行在服务端的,以及正常的vue声明周期mounted之前均是在服务端运行的,那么服务端是没有比如window对象的location.navag ...
- OBjective-C:在可变数组NSMutableArray中添加相同对象后,进行自定义的排序方式输出
以下为自定义的排序方式的实现 #import "Person+Compare.h" @implementation Person (Compare) -(NSComparisonR ...
- C#中在比较自定义对象的时候要重写Equals方法
using System;using System.Collections.Generic;using System.Text; namespace Equal{ using System; c ...
- Java中利用MessageFormat对象实现类似C# string.Format方法格式化
我们在写C#代码的时候常常会使用到string.Format("待格式化字符串{0},{1},....",参数1,参数2,...),来格式化字符串,特别是拼接字符的时候,这种方式使 ...
- hibernate中对象集合的保存
一.在java web设计中经常使用对象进行操作,在hibernate中对象集合的保存(一对多) 1需要进行如下步骤: 1) 设计数据表关系 2)引入jar包,需要注意引入数据库connector 3 ...
- 《java入门第一季》之HashSet存储自定义对象问题以及注意事项
上一篇http://blog.csdn.net/qq_32059827/article/details/51578158 写到存储字符串类型的时候出现了无序,而且这个无序不是随机那种无序,它是有一定存 ...
随机推荐
- .Net Core中文编码问题整理
1..Net Core Console控制台程序 在.Net Core中默认System.Text中不支持CodePagesEncodingProvider.Instance, System.Text ...
- 浅谈volatile与automicInteger
在并发环境中有三个因素需要慎重考量,原子性.可见性.有序性. voatile 保证了有序性(防止指令冲排序)和变量的内存可见性(每次都强制取主存数据),每次取到volatile变量一定是最新的 ...
- 【没有注意过的细节】用scanf读一个unsigned char? %hhu 的用法
头段时间我的代码,有一个 unsigned char,我需要从sscanf 中读取字符串为这个值.但是一般char 是用%c的,我是要值得. 所以我使用了%d %u来读,结果报警告: unsigned ...
- VNC XEN 双鼠标问题 以及 使用 virt-manager 工具创建的 Xen 虚拟机配置文件不在 /etc/xen/ 目录中了
0.本人用的是Ubuntu 12.04,在其中安装xen 4.1,用的是virt-manager安装虚拟机 1.VNC XEN 双鼠标问题,在配置文件中加入: 找到:(usb 1),在之后加入: (u ...
- 奇怪吸引子---Chua
奇怪吸引子是混沌学的重要组成理论,用于演化过程的终极状态,具有如下特征:终极性.稳定性.吸引性.吸引子是一个数学概念,描写运动的收敛类型.它是指这样的一个集合,当时间趋于无穷大时,在任何一个有界集上出 ...
- json传输二进制的方案【转】
本文转自:http://wiyi.org/binary-to-string.html json 是一种很简洁的协议,但可惜的是,它只能传递基本的数型(int,long,string等),但不能传递by ...
- ZMQ和MessagePack的简单使用(转)
近段日子在做一个比较复杂的项目,其中用到了开源软件ZMQ和MessagePack.ZMQ对底层网络通信进行了封装,是一个消息处理队列库, 使用起来非常方便.MessagePack是一个基于二进制的对象 ...
- Android开发者选项 介绍
15个必知的Android开发者选项 https://www.jianshu.com/p/07b551ee260b 1.Stay awake 充电时保持屏幕唤醒,开发的时候,时不时的锁屏真是够了,开 ...
- JS中三目运算符和if else的区别,你弄得明白吗
今天写了一个图片轮播的小demo,用到了判断 先试了一下if else,代码如下: if(n >= count-1){ n =0; }else{ n ++; } 随后代码写完了,准备优化 ...
- android linux 内核层
Android依赖于Linux2.6内核提高的高核心系统服务,例如安全,内存管理,进程管理,网络斎等等方面内容.内核作为一个抽象层,存在与硬件层和软件层之间.android对Linux下面内容做了增强 ...