找出非重复元素(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));