问题描述
C#/.NET应用程序编程开发中,如何使用LINQ实现按集合元素的某个属性分组(GroupBy)后查询分组的子集合?
比如,现有一个订单集合,其中每个订单信息(Order.cs
)包含:订单编号,客户姓名,订单金额,创建时间。订单实体类定义如下:
/// <summary>
/// 订单实体
/// </summary>
class Order
{
/// <summary>
/// 订单编号
/// </summary>
public string OrderNo { get; set; }
/// <summary>
/// 客户姓名
/// </summary>
public string CustomerName { get; set; }
/// <summary>
/// 订单金额
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedOn { get; set; }
}
测试数据如下:
var orders = new List<Order> {
new Order{OrderNo="0000001",CreatedOn=DateTime.Now,Amount=56.55M,CustomerName="Rector"},
new Order{OrderNo="0000002",CreatedOn=DateTime.Now,Amount=28.88M,CustomerName="Liu"},
new Order{OrderNo="0000003",CreatedOn=DateTime.Now,Amount=98.15M,CustomerName="Curry"},
new Order{OrderNo="0000004",CreatedOn=DateTime.Now,Amount=39.50M,CustomerName="Rector"},
new Order{OrderNo="0000005",CreatedOn=DateTime.Now,Amount=24.00M,CustomerName="Liu"},
new Order{OrderNo="0000006",CreatedOn=DateTime.Now,Amount=86.69M,CustomerName="Curry"},
new Order{OrderNo="0000007",CreatedOn=DateTime.Now,Amount=105.85M,CustomerName="Rector"},
};
需要使用LINQ按用户名对订单集合分组(GroupBy)后的子集合为:
Customer name:Rector
================[Order info]================
No:0000001,CreatedOn:2019-07-04 13:38:12,Amount:56.55,CustomerName:Rector
No:0000004,CreatedOn:2019-07-04 13:38:12,Amount:39.50,CustomerName:Rector
No:0000007,CreatedOn:2019-07-04 13:38:12,Amount:105.85,CustomerName:Rector
Customer name:Liu
================[Order info]================
No:0000002,CreatedOn:2019-07-04 13:38:12,Amount:28.88,CustomerName:Liu
No:0000005,CreatedOn:2019-07-04 13:38:12,Amount:24.00,CustomerName:Liu
Customer name:Curry
================[Order info]================
No:0000003,CreatedOn:2019-07-04 13:38:12,Amount:98.15,CustomerName:Curry
No:0000006,CreatedOn:2019-07-04 13:38:12,Amount:86.69,CustomerName:Curry
在不使用LINQ查询语句或者LINQ表达式的情况下,我们通常只能用循环来处理类似的分组问题。
那么,使用LINQ又该如何实现以上的分组查询结果呢?
方案一
使用GroupBy
分组,然后再Select
一个匿名子集合,如下:
var groups = orders.GroupBy(g => g.CustomerName)
.Select(x => new { CustomerName = x.Key, Orders = x.ToList() });
完整示例:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp2
{
class Program
{
public static void Main()
{
var orders = new List<Order> {
new Order{OrderNo="0000001",CreatedOn=DateTime.Now,Amount=56.55M,CustomerName="Rector"},
new Order{OrderNo="0000002",CreatedOn=DateTime.Now,Amount=28.88M,CustomerName="Liu"},
new Order{OrderNo="0000003",CreatedOn=DateTime.Now,Amount=98.15M,CustomerName="Curry"},
new Order{OrderNo="0000004",CreatedOn=DateTime.Now,Amount=39.50M,CustomerName="Rector"},
new Order{OrderNo="0000005",CreatedOn=DateTime.Now,Amount=24.00M,CustomerName="Liu"},
new Order{OrderNo="0000006",CreatedOn=DateTime.Now,Amount=86.69M,CustomerName="Curry"},
new Order{OrderNo="0000007",CreatedOn=DateTime.Now,Amount=105.85M,CustomerName="Rector"},
};
RunTest(orders);
Console.ReadLine();
}
private static void RunTest(List<Order> orders)
{
var groups = orders.GroupBy(g => g.CustomerName)
.Select(x => new { CustomerName = x.Key, Orders = x.ToList() });
foreach (var group in groups)
{
Console.WriteLine("Customer name:{0}", group.CustomerName);
Console.WriteLine("================[Order info]================");
foreach (var order in group.Orders)
{
Console.WriteLine("No:{0},CreatedOn:{1},Amount:{2},CustomerName:{3}", order.OrderNo, order.CreatedOn, order.Amount, order.CustomerName);
}
}
}
}
/// <summary>
/// 订单实体
/// </summary>
class Order
{
/// <summary>
/// 订单编号
/// </summary>
public string OrderNo { get; set; }
/// <summary>
/// 客户姓名
/// </summary>
public string CustomerName { get; set; }
/// <summary>
/// 订单金额
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedOn { get; set; }
}
}
方案二
使用LINQ的查询表达式,如下:
var groups = (from o in orders
group o by o.CustomerName into g
select new
{
CustomerName = g.Key,
Orders = g.ToList()
});
完整示例:
using System;
using System.Collections.Generic;
using System.Linq;
namespace ConsoleApp2
{
class Program
{
public static void Main()
{
var orders = new List<Order> {
new Order{OrderNo="0000001",CreatedOn=DateTime.Now,Amount=56.55M,CustomerName="Rector"},
new Order{OrderNo="0000002",CreatedOn=DateTime.Now,Amount=28.88M,CustomerName="Liu"},
new Order{OrderNo="0000003",CreatedOn=DateTime.Now,Amount=98.15M,CustomerName="Curry"},
new Order{OrderNo="0000004",CreatedOn=DateTime.Now,Amount=39.50M,CustomerName="Rector"},
new Order{OrderNo="0000005",CreatedOn=DateTime.Now,Amount=24.00M,CustomerName="Liu"},
new Order{OrderNo="0000006",CreatedOn=DateTime.Now,Amount=86.69M,CustomerName="Curry"},
new Order{OrderNo="0000007",CreatedOn=DateTime.Now,Amount=105.85M,CustomerName="Rector"},
};
RunTest(orders);
Console.ReadLine();
}
private static void RunTest(List<Order> orders)
{
var groups = (from o in orders
group o by o.CustomerName into g
select new
{
CustomerName = g.Key,
Orders = g.ToList()
});
foreach (var group in groups)
{
Console.WriteLine("Customer name:{0}", group.CustomerName);
Console.WriteLine("================[Order info]================");
foreach (var order in group.Orders)
{
Console.WriteLine("No:{0},CreatedOn:{1},Amount:{2},CustomerName:{3}", order.OrderNo, order.CreatedOn, order.Amount, order.CustomerName);
}
}
}
}
/// <summary>
/// 订单实体
/// </summary>
class Order
{
/// <summary>
/// 订单编号
/// </summary>
public string OrderNo { get; set; }
/// <summary>
/// 客户姓名
/// </summary>
public string CustomerName { get; set; }
/// <summary>
/// 订单金额
/// </summary>
public decimal Amount { get; set; }
/// <summary>
/// 创建时间
/// </summary>
public DateTime CreatedOn { get; set; }
}
}
版权声明:本作品系原创,版权归码友网所有,如未经许可,禁止任何形式转载,违者必究。
发表评论
登录用户才能发表评论, 请 登 录 或者 注册