【笔记】【LINQ编程技术内幕】第七章 对查询进行排序和分组

对信息进行排序

通过orderby关键字,LINQ可以实现升序和降序排列。LINQ还支持次要排序(也可以按升序和降序排列),只要将需要排序的项用逗号隔开即可。

升序,将一句话中的单词拆开,然后将这些单词升序排列

string quote = "Most people have the will to win, few have the will to prepare to win.";
string[] words = quote.Split(new char[] { ' ', ',', '.' }, StringSplitOptions.RemoveEmptyEntries);

// 依据指定的内容进行升序排列,同时 `ascending`可以省略,因为默认执行升序排列
var sorted = from word in words 
             orderby word ascending
             select word;

foreach (var s in sorted)
	Console.WriteLine(s);

降序

string quote = "Most people have the will to win, few have the will to prepare to win.";
string[] words = quote.Split(new char[] { ' ', ',', '.' }, StringSplitOptions.RemoveEmptyEntries);
var descending = from word in words 
                 orderby word descending
                 select word;

foreach (var s in descending)
	Console.WriteLine(s);

扩展方法降序

string quote = "Most people have the will to win, few have the will to prepare to win.";
string[] words = quote.Split(new char[] { ' ', ',', '.' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var s in words.OrderByDescending(s => s))
	Console.WriteLine(s);

次要排序

var gamblers = new[]
{
	new {LastName="Kimmel",  First="Paul", Age=41},
	new {LastName="Swanson", First="Dena", Age=26},
	new {LastName="Swanson", First="Joe",  Age=4},
	new {LastName="Kimmel",  First="Noah", Age=11}
};

// 在关键字 orderby 之后,列举出的项是排序依据项,其中排序优先级依次降低。同时每个依据项可天降ascending或descending关键字用于指定是升序还是降序排列
var sordid = from gambler in gamblers
			 orderby gambler.LastName, gambler.Age
			 select gambler;

foreach (var playa in sordid)
	Console.WriteLine(playa);

// 实现相同功能的拓展方法版本
gamblers.OrderBy(item=>item.LastName).ThenBy(item=>item.Age).Select(item=>item);

反转顺序

string quote = "Most people have the will to win, few have the will to prepare to win.";
string[] words = quote.Split(new char[] { ' ', ',', '.' }, StringSplitOptions.RemoveEmptyEntries);

foreach (var s in words.Reverse())
	Console.WriteLine(s);

对信息进行分组

LINQ中的许多概念都跟SQL很相似。其中之一就是根据相似性将数据组织到逻辑分组中。在LINQ中,分组功能是通过group by子句实现的。

var nums = new int[] { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 };
// 根据条件执行分组,该例中 n % 2 只有两个值0和1,结果被分为两组
// 如果使用 n % 3 则会被分成 3 组
var result = from n in nums group n by n % 2;

// really quite funky
Array.ForEach(result.ToArray(), x =>
{
	Console.WriteLine(x.Key == 0 ? "evens:" : "odds:");
	Array.ForEach(x.ToArray(), y => Console.WriteLine(y));
});

数据库查询 + LINQ分组

class Program
{
	// 查询语句,内连接。左表中一条记录可连接右表中满足条件的多条记录
	static string sql = "SELECT Categories.CategoryName, Products.ProductID, Products.ProductName, Products.UnitsInStock, Products.UnitPrice " +
	                    "FROM Categories INNER JOIN Products ON Categories.CategoryID = Products.CategoryID";

	// 连接字符串
	static string connectionString = "Server=localhost;Database=Northwind;Trusted_Connection=True;";

	// 定义一个数据类,用于存储SQL查询的单条记录
	public class ProductItem
	{
		public string CategoryName { get; set; }
		public int ProductID { get; set; }
		public string ProductName { get; set; }
		public int UnitsInStock { get; set; }
		public decimal UnitPrice { get; set; }

		public override string ToString()
		{
			const string mask = "Category Name: {0}, Product ID: {1}, Product Name: {2}, Units In Stock: {3}, Unit Price: {4}";
			return string.Format(mask, CategoryName, ProductID, ProductName, UnitsInStock, UnitPrice);
		}
	}

	// 读取辅助类,用以判断是否为空值
	static T SafeRead<T>(IDataReader reader, string name, T defaultValue)
	{
		object o = reader[name];
		if (o != System.DBNull.Value && o != null)
			return (T)Convert.ChangeType(o, defaultValue.GetType());

		return defaultValue;
	}

	static void Main(string[] args)
	{
		// 定义存储查询结果的集合
		List<ProductItem> products = new List<ProductItem>();

		// 执行查询
		using (SqlConnection connection = new SqlConnection(connectionString))
		{
			connection.Open();
			SqlCommand command = new SqlCommand(sql, connection);
			SqlDataReader reader = command.ExecuteReader();
			while (reader.Read())
			{
				products.Add(new ProductItem
				{
					CategoryName = SafeRead(reader, "CategoryName", ""),
					ProductID = SafeRead(reader, "ProductID", -1),
					ProductName = SafeRead(reader, "ProductName", ""),
					UnitsInStock = SafeRead(reader, "UnitsInStock", 0),
					UnitPrice = SafeRead(reader, "UnitPrice", 0M)
				});
			}
		}
		
		// 分割线
		string line = new string('-', 40);

		// 定义LINQ
		// 将分组结果被组织到IGrouping对象中,该对象含有一个Key/Element对。
		// Key代表的是含有数据的分组,而Element则代表的是数据
		// 通过 into 子句将分组结果存储于指定的变量grp中
		var grouped = from p in products
					  orderby p.CategoryName, p.ProductName
					  group p by p.CategoryName into grp
					  select new { Category = grp.Key, Product = grp };

		// 打印结果
		Array.ForEach(grouped.ToArray(), g =>
		{
			Console.WriteLine(g.Category);
			Console.WriteLine(line);
			
		  	// dump each product in the group
		  	Array.ForEach(g.Product.ToArray(), p => Console.WriteLine(p));
			Console.WriteLine(Environment.NewLine);
		});
		
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

zhy29563

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值