【笔记】【LINQ编程技术内幕】第九章 执行集合运算

    技术2022-07-11  86

    找出非重复元素(Distinct)

    从一组表示成绩的数字中计算出中间成绩

    var grades = new int[]{ 65, 72, 72, 75, 75, 77, 79, 80, 81, 81, 81, 85, 88, 91, 92, 92, 92, 95, 99, 100 }; var distinct = grades.Distinct(); Console.WriteLine("Median grade: {0}", distinct.ToArray<int>()[distinct.Count() / 2]);

    通过对象的字段找出非重复对象

    假设你有一个销售团队,而且你现在需要评估产品所销往的那些城市。该示例使用Distinct方法来找出城市的非重复列表。

    class Program { static void Main(string[] args) { List<Order> orders = GetOrders(); Array.ForEach(orders.ToArray(), o => Console.WriteLine(Dump(o))); Console.WriteLine(orders.Count); // version 1 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()); } public static string Dump<T>(T obj) { Type t = typeof(T); StringBuilder builder = new StringBuilder(); PropertyInfo[] infos = t.GetProperties(); // feel the enmity of your peers if you write code like this 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(); } public static List<Order> GetOrders() { string connectionString ="Server=localhost;Database=Northwind;Trusted_Connection=True;"; List<Order> orders = new List<Order>(); using (IDbConnection connection = new SqlConnection(connectionString)) { connection.Open(); IDbCommand command = new SqlCommand("SELECT * FROM Orders"); command.Connection = connection; command.CommandType = CommandType.Text; IDataReader reader = command.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), RequiredDate = 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; } } class CityComparer : IEqualityComparer<Order> { #region IEqualityComparer<Order> Members 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(); } #endregion } class Order { public int? OrderID { get; set; } public string CustomerID { get; set; } public int? EmployeeID { get; set; } public DateTime? OrderDate { get; set; } public DateTime? RequiredDate { 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; } }

    通过Intersect(交集) 和 Except(差集)定义集合

    var evens = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 19, 20, 22, 24, 26, 28, 30, 32, 34 }; var fibos = new int[] { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; // Except 返回源序列中有而目标序列中没有的那些元素 var setDifference = evens.Except(fibos); Array.ForEach<int>(setDifference.ToArray(), e => Console.WriteLine(e)); Console.WriteLine(); // Intersect 返回原序列和目标序列中都有哪些元素 var intersect = evens.Intersect(fibos); Array.ForEach<int>(intersect.ToArray(), e => Console.WriteLine(e));

    使用Union(并集)创建复合结果集

    Union扩展方法将两个序列合并到一起毛病返回这个两个序列中唯一成员。如果自己变量代码将两个序列的所有元素加起来,然后在结果上调用Distinct,那么产生的结果与Union相同。

    var evens = new int[] { 2, 4, 6, 8, 10, 12, 14, 16, 19, 20, 22, 24, 26, 28, 30, 32, 34 }; var fibos = new int[] { 1, 1, 2, 3, 5, 8, 13, 21, 34 }; var union = evens.Union(fibos); Array.ForEach<int>(union.ToArray(), e => Console.WriteLine(e));
    Processed: 0.013, SQL: 9