LINQ的Set method有很多,包含前幾天提到的All / Any、Contains、Distinct等,還有比較不常使用到的Union、Except和Intersect這種再高中學數學的聯集、差集與交集。今天會提一些情境可以考慮使用這些大家比較少用的Set method。
Union:計算兩個集合聯集
var numbers1 = new List<int>() {1, 2, 3};
var numbers2 = new List<int>() {2, 3, 4};
numbers1.Union(numbers2).ToList(); // 輸出{1, 2, 3, 4}
Intersect:計算兩集合的交集
var numbers1 = new List<int>() {1, 2, 3};
var numbers2 = new List<int>() {2, 3, 4};
numbers1.Intersect(numbers2).ToList(); // 輸出{2, 3}
Except:計算兩個集合的差集
var numbers1 = new List<int>() {1, 2, 3};
var numbers2 = new List<int>() {2, 3, 4};
numbers1.Except(numbers2).ToList(); // 輸出{1, 2, 3, 4}
假設我們再設計一個商品競標系統,有個類別負責儲存每個商品的即時價格。_current儲存的當前商品資訊,當有新的資訊時,系統則會透過UpdateGoods來更新即時商品價格。
public class GoodsCache
{
private List<Goods> _goods = new List<Goods>();
public void UpdateGoods(List<Goods> latestGoods)
{
_goods = latestGoods;
}
}
public class Goods
{
public int Id { get; set; }
public decimal Price { get; set; }
public override bool Equals(object obj)
{
if (obj is Goods goods)
{
return goods.Id == Id;
}
return false;
}
public override int GetHashCode()
{
return Id.GetHashCode();
}
}
當我們想知道哪些哪些商品是新上架或下架時,可以透過Except來簡單比較出新的商品或下架商品。拿最新商品集合與上一次的舊集合做差集,就能比較出這次新上架的商品集合。反之亦然,如果拿舊商品集合與新商品集合做差集,則能得出已經下架的商品。
New = latestGoods.Except(Current).ToList();
Delete = Current.Except(latestGoods).ToList();
另外我們同時也時常會需要把已經在架上商品價格更新,並提示使用者這項商品的價格已經變了。所以我們會需要哪些商品是有價格更新的。透過Intersect能輕鬆找出哪些是還在架上的商品
Goods = latestGoods.Intersect(Current).ToList();
但是這其中包含了價格不變與價格有變的兩種情況,為了顯示目的我們只需要那些價格有變的商品集合,我們可以透過自訂IEqualityComparer來幫助我們找到那些價格有變的商品。
public class GoodsPriceCompare : IEqualityComparer<Goods>
{
public bool Equals(Goods goods1, Goods goods2)
{
return goods1.Id == goods2.Id && goods1.Price != goods2.Price;
}
public int GetHashCode(Goods goods)
{
return goods.GetHashCode();
}
}
透過自訂相等的邏輯再加上intersect,我們便能更快的過濾出那些價格有變的商品。
PriceChange = latestGoods.Intersect(Current, new GoodsPriceCompare()).ToList();
鐵人賽也過去一半了,我們聊了許多關於LINQ方法的用法與一些可以使用的情境,但是還是有一些好用的LINQ方法沒有介紹到。未來如果有機會,可能會在透過一些比較實際的例子來介紹給大家。