常常在遺留代碼中發現使用IndexOf來判斷物件是否存在於陣列中,在Simple remove duplicates 中用使用IndexOf來判斷number是否存在distinctNumbers中
public int[] RemoveDuplicated(int[] numbers)
{
var distinctNumbers = new List<int>();
for (var index = numbers.Length - 1; index >= 0; index--)
{
if (distinctNumbers.IndexOf(numbers[index]) == -1)
{
distinctNumbers.Insert(0, numbers[index]);
}
}
return distinctNumbers.ToArray();
}
通常寫的人當下很清楚這個邏輯的意義,並不覺得這段代碼有什麼問題。等到之後因為需求異動,需要調整這段代碼的邏輯時,就會發現需要花一點點時間來理解,畢竟IndexOf的語意並非主要用來判斷是否包含。所以在寫的當下,應該使用更貼近邏輯語意的作法。
以上面的例子來說,應該使用Contains代替IndexOf
public int[] RemoveDuplicated(int[] numbers)
{
...
if (!distinctNumbers.Contains(numbers[index]))
{
distinctNumbers.Insert(0, numbers[index]);
}
...
}
如果是使用LINQ,也能改成使用Any來達到一樣的效果
public int[] RemoveDuplicated(int[] numbers)
{
...
if (!distinctNumbers.Any(x => x == numbers[index]))
{
distinctNumbers.Insert(0, numbers[index]);
}
...
}
還能使用LINQ的Reverse和Distinctr將代碼更進一步簡化
public int[] RemoveDuplicated(int[] numbers)
{
return numbers.Reverse().Distinct().Reverse().ToArray();
}
同一個問題可以透過許多不同的實作方式來解決,選擇意圖明顯的實作方式有助於讓代碼更好理解。使用LINQ能簡化很多複雜的寫法,這個之後會再分享一些。關於消除重複,之後也會再分享到另一個可以移除重複的方法。