Any , All and Contains 均是非常容易會使用到的方法 , 另外需要注意的是這三個方法都不具有延遲執行的特性.
Any
判斷序列的任何項目是否符合條件或包含任何項目
Any 有兩個多載方法如下
-
public static bool Any<TSource> (this IEnumerable<TSource> source);
- 判斷序列中包含的項目數是否不為零
-
public static bool Any<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
- 判斷序列中的任何項目是否有任何一個符合條件
- 實作上與 First 類似 , 差別在於回傳值. First 會回傳第一個符合條件的項目 , Any 則是發現第一個符合條件的項目時會回傳 true , 反之若沒有任何項目符合條件會回傳 false
使用時機
- 需要判斷集合是否包含任何項目.
- 需要使用 predicate 表達指定的項目 , 以判斷集合中是否存在某個指定項目
Any 的用法
// 列出每個人持有的電話 , 若是他沒有電話則不要列出.
static void Main(string[] args)
{
var people = new[]
{
new { Name="大名" , CellPhone = new string[]{"0989112266","03-29007536"}},
new { Name="小黃" , CellPhone = new string[]{"0961334475"}},
new { Name="大龍" , CellPhone = new string[]{}},
new { Name="包子" , CellPhone = new string[]{"0953793211", "0961751112", "0975362475"}}
};
// 使用 Where 篩選出有電話的人 , 透過 Any 判斷這個人是否有電話
var query = people.Where(person => person.CellPhone.Any())
.SelectMany((person) => person.CellPhone, (person, phone) => $"{person.Name} 持有的手機號碼是 {phone}");
// 阿龍沒有手機 , 所以不會 print 阿龍出來
foreach (var item in query)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
輸出結果
大名 持有的手機號碼是 0989112266
大名 持有的手機號碼是 03-29007536
小黃 持有的手機號碼是 0961334475
包子 持有的手機號碼是 0953793211
包子 持有的手機號碼是 0961751112
包子 持有的手機號碼是 0975362475
// 找出持有 03- 的電話的人所持有的手機號碼
static void Main(string[] args)
{
var people = new[]
{
new { Name="大名" , CellPhone = new string[]{"0989112266","03-29007536"}},
new { Name="小黃" , CellPhone = new string[]{"0961334475"}},
new { Name="大龍" , CellPhone = new string[]{}},
new { Name="包子" , CellPhone = new string[]{"0953793211", "0961751112", "0975362475"}}
};
// 透過 Any 判斷這個人是否持有 03- 開頭的手機
var query = people.Where(person => person.CellPhone.Any(num => num.Contains("03-")))
.SelectMany((person) => person.CellPhone, (person, phone) => $"{person.Name} 持有的手機號碼是 {phone}");
foreach (var item in query)
{
Console.WriteLine(item);
}
Console.ReadKey();
}
輸出結果
大名 持有的手機號碼是 0989112266
大名 持有的手機號碼是 03-29007536
簡單實作自己的 Any
public static bool MyAny<TSource>(this IEnumerable<TSource> source)
{
if (source is null)
{
throw new Exception("source is null");
}
return source.GetEnumerator().MoveNext();
}
public static bool MyAny<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source is null || predicate is null)
{
throw new Exception("either source or predicate is null");
}
foreach (var item in source)
{
if (predicate(item))
{
return true;
}
}
return false;
}
All
判斷序列的所有項目是否全都符合條件
public static bool All<TSource> (this IEnumerable<TSource> source, Func<TSource,bool> predicate);
使用時機
- 需要使用 predicate 表達指定的項目 , 以判斷集合中項目是否全都滿足這個指定項目
All 的用法
class Pet
{
public string Name { get; set; }
public int Age { get; set; }
}
static void Main(string[] args)
{
// Create an array of Pets.
Pet[] pets = { new Pet { Name="Barley", Age=10 },
new Pet { Name="Boots", Age=4 },
new Pet { Name="Whiskers", Age=6 }
};
// Determine whether all pet names
// in the array start with 'B'.
bool allStartWithB = pets.All(pet => pet.Name.StartsWith("B"));
Console.WriteLine("{0} pet names start with 'B'.", allStartWithB ? "All" : "Not all");
Console.ReadKey();
}
輸出結果
Not all pet names start with ‘B’.
簡單實作自己的 All
public static bool MyAll<TSource>(this IEnumerable<TSource> source, Func<TSource, bool> predicate)
{
if (source is null || predicate is null)
{
throw new Exception("source or predicate is null");
}
foreach (var element in source)
{
if (!predicate(element))
{
return false;
}
}
return true;
}
Contains
判斷序列是否包含指定的項目
Contains 有兩個多載方法
- public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value);
- 使用預設的相等比較子 (Comparer) 來判斷序列是否包含指定的項目。
- public static bool Contains<TSource> (this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer);
- 使用指定的 IEqualityComparer<T> 來判斷序列是否包含指定的項目。
使用時機
- 想要找到指定的某個項目是否已存在於集合中.
Contains 的用法
// 判斷 fruits 中是否存在 mango
static void Main(string[] args)
{
string[] fruits = { "apple", "banana", "mango", "orange", "passionfruit", "grape" };
string fruit = "mango";
bool hasMango = fruits.Contains(fruit);
Console.WriteLine("The array {0} contain '{1}'.", hasMango ? "does" : "does not", fruit);
Console.ReadKey();
}
輸出結果
The array does contain ‘mango’.
class EqualityComparer<TSource> : IEqualityComparer<TSource> where TSource : class
{
private PropertyInfo[] properties = null;
public bool Equals(TSource x, TSource y)
{
if (properties == null)
properties = x.GetType().GetProperties();
return properties.Aggregate(true, (result, item) =>
{
return result && item.GetValue(x).Equals(item.GetValue(y));
});
}
public int GetHashCode(TSource obj)
{
if (properties == null)
properties = obj.GetType().GetProperties();
return properties.Aggregate(0, (result, item) =>
{
return result ^ item.GetValue(obj).GetHashCode();
});
}
}
public class Product
{
public string Name { get; set; }
public int Code { get; set; }
}
static void Main(string[] args)
{
Product[] fruits = {
new Product { Name = "apple", Code = 9 },
new Product { Name = "orange", Code = 4 },
new Product { Name = "lemon", Code = 12 }
};
Product apple = new Product { Name = "apple", Code = 9 };
Product kiwi = new Product { Name = "kiwi", Code = 8 };
EqualityComparer<Product> prodc = new EqualityComparer<Product>();
bool hasApple = fruits.Contains(apple, prodc);
bool hasKiwi = fruits.Contains(kiwi, prodc);
Console.WriteLine("Apple? " + hasApple);
Console.WriteLine("Kiwi? " + hasKiwi);
Console.ReadKey();
}
輸出結果
Apple? True
Kiwi? False
簡單實作自己的 Contains
public static bool MyContains<TSource>(this IEnumerable<TSource> source, TSource value)
{
if (source is null)
{
throw new Exception("source is null");
}
foreach (var element in source)
{
if (element.Equals(value))
{
return true;
}
}
return false;
}
public static bool MyContains<TSource>(this IEnumerable<TSource> source, TSource value, IEqualityComparer<TSource> comparer)
{
if (source is null || comparer is null)
{
throw new Exception("source or comparer is null");
}
foreach (var element in source)
{
if (comparer.Equals(element, value))
{
return true;
}
}
return false;
}
Summary
- Any 和 Contains 均可以用來判斷集合中是否包含指定的項目 , 其差別在於 Any 是透過 predicate 表達指定的項目 , 而 Contains 則是直接丟入指定的項目.
Thank you!
You can find me on
若有謬誤 , 煩請告知 , 新手發帖請多包涵