集合运算

一、Distinct

     Distinct用于测试集合中的元素并忽略重复值。Dintinct既可以在一个序列上调用,也可以在一个实现了IEquallity-Comparer的对象上调用。
【示例】

1.1 定义实体类

using System;

namespace 通过对象的字段找出非重复对象
{
    /// <summary>
    /// 实体类
    /// </summary>
    public class Order
    {
        //使用自动属性时,需记住:自动属性只能实现最基本的设置器和获取器,
        //且无法直接引用字段
        public int? OrderID { get; set; }
        public string CustomerID { get; set; }
        public int? EmployeeID { get; set; }
        public DateTime? OrderDate { get; set; }
        public DateTime? RequireDate { get; set; }
        public DateTime? ShippedDate { get; set; }
        public int? ShipVia { get; set; }
        public decimal? Freight { get; set; }
        public string ShipName { get; set; }
        public string ShipAddress { get; set; }
        public string ShipCity { get; set; }
        public string ShipRegion { get; set; }
        public string ShipPostalCode { get; set; }
        public string ShipCountry { get; set; }
    }
}

分析 :使用可空类型,这样就可以给值类型字段赋空值。

1.2 定义一个方法,用于从数据库中取出值、赋值并进行空值处理

/// <summary>
        /// 从数据库中取出值放入集合中
        /// </summary>
        /// <returns></returns>
        public static List<Order> GetOrders()
        {
            //设置连接字符串,最好放在配置文件中
            string connectionString = "xxxxxxxxxxxxxxxxxxxxxx";
            //定义一个集合,该集合用于存放Order类对象
            List<Order> orders = new List<Order>();
            using(SqlConnection con=new SqlConnection(connectionString))
            {
                con.Open();
                SqlCommand com = new SqlCommand("select * from Orders");
                com.Connection = con;
                com.CommandType = CommandType.Text;
                SqlDataReader reader = com.ExecuteReader();
                while (reader.Read())
                {
                    orders.Add(new Order
                    {
                        OrderID = reader.IsDBNull(0) ? null : (int?)reader.GetInt32(0),
                        CustomerID = reader.IsDBNull(1) ? null : reader.GetString(1),
                        EmployeeID = reader.IsDBNull(2) ? null : (int?)reader.GetInt32(2),
                        OrderDate= reader.IsDBNull(3) ? null :(DateTime?)reader.GetDateTime(3),
                        RequireDate= reader.IsDBNull(4) ? null : (DateTime?)reader.GetDateTime(4),
                        ShippedDate= reader.IsDBNull(5) ? null : (DateTime?)reader.GetDateTime(5),
                        ShipVia= reader.IsDBNull(6) ? null : (int?)reader.GetInt32(6),
                        Freight= reader.IsDBNull(7) ? null : (decimal?)reader.GetDecimal(7),
                        ShipName= reader.IsDBNull(8) ? null : reader.GetString(8),
                        ShipAddress= reader.IsDBNull(9) ? null : reader.GetString(9),
                        ShipCity= reader.IsDBNull(10) ? null : reader.GetString(10),
                        ShipRegion= reader.IsDBNull(11) ? null : reader.GetString(11),
                        ShipPostalCode= reader.IsDBNull(12) ? null : reader.GetString(12),
                        ShipCountry= reader.IsDBNull(13) ? null : reader.GetString(13),
                    });
                }
            }
            return orders;
        }

1.3 实现一个IEqualityComparer

      在Order对象上执行自定义的比较操作。
using System.Collections.Generic;

namespace 通过对象的字段找出非重复对象
{
    /// <summary>
    /// 在Order对象上执行自定义的比较操作
    /// </summary>
    public class CityComparer : IEqualityComparer<Order>
    {
        public bool Equals(Order x, Order y)
        {
            return x.ShipCity == null || y.ShipCity == null ? false : x.ShipCity.Equals(y.ShipCity);
        }

        public int GetHashCode(Order obj)
        {
            return obj.ShipCity == null ? -1 : obj.ShipCity.GetHashCode();
        }
    }
}

1.4 对象转换器

       转储器通过一个StringBuilder和发射来获取公共属性(代表着一个对象的状态),然后迭代这些属性并显示各个属性的名称和值。
/// <summary>
        /// 一个基于反射和属性的通用对象转储器实用工具
        /// </summary>
        public static string Dump<T>(T obj)
        {
            //Type--表示类型声明:类类型、接口类型、数组类型、值类型、枚举类型、类型参数、泛型类型定义,
            //以及开放或封闭构造的泛型类型。
            Type t = typeof(T);
            StringBuilder builder = new StringBuilder();
            //GetProperties:返回当前 System.Type 的所有公共属性。
            //返回结果:
            //     表示当前 System.Type 的所有公共属性的 System.Reflection.PropertyInfo 对象数组。- 或 -如果当前 System.Type
            //     没有公共属性,则为 System.Reflection.PropertyInfo 类型的空数组。
            PropertyInfo[] infos = t.GetProperties();

            
            Array.ForEach(infos.ToArray(), p => builder.AppendFormat("{0}={1} ", p.Name,
                 p.GetValue(obj, null) == null ? "" : p.GetValue(obj, null)));
            builder.AppendLine();

            return builder.ToString();
        }

1.5 执行

/// <summary>
        /// Demonstrates distinct ship city
        /// </summary>
        /// <param name="args"></param>
        static void Main(string[] args)
        {
            List<Order> orders = GetOrders();

            Array.ForEach(orders.ToArray(), o => Console.WriteLine(Dump(o)));
            Console.WriteLine(orders.Count());

            //version1 with extension method OrderBy
            var cities = orders.Distinct(new CityComparer());
            Array.ForEach(cities.OrderBy(o => o.ShipCity).ToArray(),
                orderedByCity => Console.WriteLine(orderedByCity.ShipCity));


            //version 2 with query
            var cities2 = from order in orders.Distinct(new CityComparer())
                          orderby order.ShipCity
                          select order;
            Array.ForEach(cities2.ToArray(),
                orderedByCity => Console.WriteLine(orderedByCity.ShipCity));
            Console.WriteLine(cities.Count());
            Console.ReadKey();
        }

二、通过Intersect和Except定义集合
        Intersect扩展方法将参数序列与源序列进行比较,然后返回源序列和目标序列中都有的那些元素。
        Except扩展方法返回源序列(调用Except的那个序列)中有而目标序列中没有的那些元素。
【示例】
using System;
using System.Linq;

namespace 计算集合的区别并显示结果
{
    class Program
    {
        static void Main(string[] args)
        {
            var number1 = new int[] { 2, 3, 4, 5, 12, 23, 34 };
            var number2 = new int[] { 3, 125, 23, 43, 54, 65 };

            Console.WriteLine("得到源序列中有而目标序列中没有的那些元素:");
            var setDifference = number2.Except(number1);
            Array.ForEach(setDifference.ToArray(), n => Console.Write(n + "  "));
            Console.WriteLine();

            Console.WriteLine("得到源序列和目标序列中都有的那些元素:");
            var setSame = number1.Intersect(number2);
            Array.ForEach(setSame.ToArray(), n => Console.Write(n + "  "));
            Console.ReadKey();
        }
    }
}


三、Union复合结果集
【示例】
using System;
using System.Linq;

namespace 使用Union创建复合结果集
{
    class Program
    {
        static void Main(string[] args)
        {
            var number1 = new int[] { 2, 3, 4, 5, 12, 23, 34 };
            var number2 = new int[] { 3, 125, 23, 43, 54, 65 };

            var union = number1.Union(number2);
            Array.ForEach<int>(union.ToArray(), n => Console.Write(n+" "));
            Console.WriteLine();
            Array.ForEach<int>(union.OrderBy(n => n).ToArray(), n => Console.Write(n + " "));
            Console.ReadKey();
        }
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值