C#/.NET应用程序编程开发中如何使用LINQ实现按集合元素的某个属性分组(GroupBy)后查询分组的子集合?

C#开发 作者: Rector 8 次阅读 · 读完约需 1 分钟 收藏本文

郑重申明:本文未经许可,禁止任何形式转载

问题描述

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; }
    }
}

阅读了该文章的人还浏览了...

本文永久链接码友网 » C#/.NET应用程序编程开发中如何使用LINQ实现按集合元素的某个属性分组(GroupBy)后查询分组的子集合?

发布于: 2019-07-04 13:53:10
分享扩散:

发表评论

登录用户才能发表评论, 请 登 录 或者 注册