.NET/C#中对自定义对象集合进行自定义排序的方法
2018-01-09 21:35
507 查看
一个集合可否排序,要看系统知不知道排序的规则,像内建的系统类型,int ,string,short,decimal这些,系统知道怎么排序,而如果一个集合里面放置的是自定义类型,比如自己定义了一个Car类型,要把它排序,系统是不知道怎么办的。
那么,如何告知系统排序的规则呢?有以下几种方法:
1:对类实现IComparable接口,示例如下:
[csharp] view plain copy
print?
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 类的对象。
[csharp] view plain copy
print?
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接口来得简洁。
这种方法可以用匿名方法进行改进:
[csharp] view plain copy
print?
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表达式改进,如下:
[csharp] view plain copy
print?
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);
}
}
}
}
变态的是,还可以进一步改进,使用扩展方法,如下:
[csharp] view plain copy
print?
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子句实现排序。
“
?
那么,如何告知系统排序的规则呢?有以下几种方法:
1:对类实现IComparable接口,示例如下:
[csharp] view plain copy
print?
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 类的对象。
[csharp] view plain copy
print?
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接口来得简洁。
这种方法可以用匿名方法进行改进:
[csharp] view plain copy
print?
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表达式改进,如下:
[csharp] view plain copy
print?
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);
}
}
}
}
变态的是,还可以进一步改进,使用扩展方法,如下:
[csharp] view plain copy
print?
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子句实现排序。
“
?
相关文章推荐
- .NET/C#中对自定义对象集合进行自定义排序的方法
- .NET/C#中对自定义对象集合进行自定义排序的方法
- .NET/C#中对自定义对象集合进行自定义排序的方法
- .NET/C#中对对象集合进行查询的方法 以及相关的 Predicate<T> 及 Action<T> 的用法
- .NET/C#中对对象集合进行查询的方法 以及相关的 Predicate<T> 及 Action<T> 的用法
- 对集合中的对象进行排序,用collections.sort 到方法
- Sql2012如何将远程服务器数据库及表、表结构、表数据导入本地数据库 自定义日志记录功能,按日记录,很方便 C#常量和字段以及各种方法的语法总结 类型,对象,线程栈,托管堆在运行时的关系,以及clr如何调用静态方法,实例方法,和虚方法 asp.net webapi 自定义身份验证
- 对自定义对象集合List中的数据进行排序
- Java 往TreeSet集合中存储自定义对象学生,按照学生的年龄进行排序。
- 重写Compare方法对集合以指定对象的属性进行排序
- 重写Compare方法对集合以指定对象的属性进行排序
- C#中对List<Object>泛型集合,根据对象的某一属性进行升序排序
- Java:对集合中的对象进行排序需要实现Interface Comparable接口并实现int compareTo(T o)方法
- C#中List或其它集合对象排序方法的一点理解
- 对于集合内装载的对象数据进行自定义排序 !
- Java:集合,对列表(List)中的自定义对象按属性(字段)排序(正序、倒序)的方法
- .NET/C#中对对象集合进行查询的方法 以及相关的 Predicate<T> 及 Action<T> 的用法
- More Effective C# 第21条、第22条 实例代码解析(可比较 可排序 自定义对象集合完整演示) IEquatable, IComparable,IEnumerable
- 对List集合中的对象进行自定义排序
- 对于集合中的自定义对象使用collections.sort 进行排序,需要实现compartor接口