首先解析這份題目要得需求是甚麼
輸入兩個字串 a1 和 a2 ,輸出的字串陣列內容為 a2每一個字串陣列元素中包含a1任一個陣列元素的的字串,並且將其排序輸出,不可重複
聽起來很饒口 就看看他的範例唄
a1是要比對的字串陣列 ["arp", "live", "strong"]
a2是要被比對的字串陣列 ["lively", "alive", "harp", "sharp", "armstrong"]
以"arp"為例,他會比對到 "harp" 和 "sharp" 但是 我的輸出只能輸出一個 "arp" 這樣
以上的範例可以方便我來拆解這一次的需求
- Contains方法 用來找尋包含的字串元素
- 比對在輸出結果有沒有重複的字串 一樣是用 Contains
- 最後的排序 OrderBy
起手就先以a1和a2各1個元素的比對來做測試案例起手,a1的元素是arp,a2的元素是aaa
程式碼如下 我預期的結果要是空的字串陣列
[TestMethod]
public void Input_arpAnd_aaa_Should_Be_EmptyArray()
{
var actual = Kata.inArray(new string[] {"arp"}, new string[] {"aaa"});
var expected = new string[] { };
Assert.AreEqual(expected,actual);
}
而Production Code 則生成了下面這個樣子
public static string[] inArray(string[] array1, string[] array2)
{
return new string[]{};
}
很理所當然的 這一個測試案例亮了第一次的紅燈
接下來用最簡單的方式讓紅燈變成綠燈,直接Return一個空的字串陣列XDDD
再來新增一個會發生錯誤且Prodction Code 更改幅度為最小的測試案例,那就是會回傳正確答案的字串了
[TestMethod]
public void Input_arpAnd_aaa_Should_Be_EmptyArray()
{
var actual = Kata.inArray(new string[] {"arp"}, new string[] {"arp"});
var expected = new string[] {"arp" };
CollectionAssert.AreEqual(expected,actual);
}
很正常的,這一個測試案例會亮你紅燈,就將程式碼更改為
public static string[] inArray(string[] array1, string[] array2)
{
List<string> result = new List<string>();
foreach (var s in array2)
{
if (s.Equals(array1[0]) )
{
result.Add(s);
}
}
return result.ToArray();
}
直接宣告一個result字串陣列變數,方便我直接用add的方法就在foreach內新增一個字元,不用去標記index為多少
然後只用一個Foreach來完成這一次的需求,並且判斷有沒有包含(這裡的Equal當初寫錯,是後來才發現寫錯的),雖然把包含方法誤寫成Equal但還是通過了測試案例,亮了綠燈
接下來新增第三個測試案例,一樣是以可能最小步的方式來思考測試案例的方向,第三個測試案例就這樣產生了
[TestMethod]
public void Input_arpAnd_aaa_Should_Be_EmptyArray()
{
var actual = Kata.inArray(new string[] {"ss", "arp"}, new string[] {"arp"});
var expected = new string[] {"arp"};
CollectionAssert.AreEqual(expected,actual);
}
因為上一個測試案例所更改的 Production Code 只有找第一個 a1 元素來做比對,這一次就故意把他新增成兩個,很理所當然的,這一個測試案例也產生了紅燈的結果
所以在 Production Code 加上了第二個 Foreach 迴圈,這個迴圈以目前的測資來說 也會是沒有問題的,所以也亮了綠燈
public static string[] inArray(string[] array1, string[] array2)
{
List<string> result = new List<string>();
foreach (var a2 in array2)
{
foreach (var a1 in array1)
{
if (a2.Equals(a1))
{
result.Add(a2);
}
}
}
return result.ToArray();
}
亮了綠燈之後要檢視程式碼
就把Production Code改成以下的樣子
public static string[] inArray(string[] array1, string[] array2)
{
var result = new List<string>();
foreach (var a1 in array1)
foreach (var a2 in array2)
if (a2.Contains(a1))
result.Add(a1);
return result.ToArray();
}
接下來再新增一個測試案例,這個測試案例是為了避免重複的結果,所以測試案例中的a2有多一個包含arp的字串
[TestMethod]
public void Input_ss_arp_And_art_starpoint_garp_Should_Be_arp()
{
var actual = Kata.inArray(new string[] { "ss", "arp" }, new string[] { "art", "starpoint","garp" });
var expected = new string[] { "arp" };
CollectionAssert.AreEqual(expected, actual);
}
一樣這一個測試案例使我的專案亮了紅燈
接下來就把Production Code更改成下面這個樣子 讓他再新增元素時除了判斷有無包含之外,還判斷原有的字串陣列中有沒有包含一樣的元素,如此一來就可以把這個測試案例亮成綠燈
public static string[] inArray(string[] array1, string[] array2)
{
var result = new List<string>();
foreach (var a1 in array1)
foreach (var a2 in array2)
if (a2.Contains(a1) && !result.Contains(a1))
result.Add(a1);
return result.ToArray();
}
再來就是最後一個需求,排序的部分,所以新增了一個需要排序才能成功的測試案例,其測試案例如下
[TestMethod]
public void Input_bc_abc_And_bbbc_dsssaabcasd_Should_Be_arp()
{
var actual = Kata.inArray(new string[] { "bc","abc" }, new string[] { "bbbc","dsssaabcasd"});
var expected = new string[] { "abc","bc" };
CollectionAssert.AreEqual(expected, actual);
}
這個測試案例我故意把 a 開頭的比較字串放在 a1 的第二個元素 b開頭擺在第一個,如此一來我的測試案例就會亮紅燈
接下來只需要在我返回字串陣列的時候用Linq排序就可以完成這個需求了,也因此亮了綠燈
public static string[] inArray(string[] array1, string[] array2)
{
var result = new List<string>();
foreach (var a1 in array1)
foreach (var a2 in array2)
if (a2.Contains(a1) && !result.Contains(a1))
result.Add(a1);
return result.OrderBy(x => x).ToArray();
}
這一次的所有測試案例如下
[TestClass]
public class UnitTest1
{
[TestMethod]
public void Input_arpAnd_aaa_Should_Be_EmptyArray()
{
var actual = Kata.inArray(new string[] { "arp" }, new string[] { "aaa" });
var expected = new string[] { };
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void Input_arpAndarp_Should_Be_arpOfArray()
{
var actual = Kata.inArray(new string[] { "arp" }, new string[] { "arp" });
var expected = new string[] { "arp" };
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void Input_ss_arpAndarp_Should_Be_arpOfArray()
{
var actual = Kata.inArray(new string[] { "ss", "arp" }, new string[] { "arp" });
var expected = new string[] { "arp" };
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void Input_ss_arp_And_art_starpoint_Should_Be_arp()
{
var actual = Kata.inArray(new string[] { "ss", "arp" }, new string[] { "art", "starpoint" });
var expected = new string[] { "arp" };
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void Input_ss_arp_And_art_starpoint_garp_Should_Be_arp()
{
var actual = Kata.inArray(new string[] { "ss", "arp" }, new string[] { "art", "starpoint","garp" });
var expected = new string[] { "arp" };
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void Input_bc_abc_And_bbbc_dsssaabcasd_Should_Be_arp()
{
var actual = Kata.inArray(new string[] { "bc","abc" }, new string[] { "bbbc","dsssaabcasd"});
var expected = new string[] { "abc","bc" };
CollectionAssert.AreEqual(expected, actual);
}
[TestMethod]
public void CodewarsExampleTest()
{
var actual = Kata.inArray(new string[] { "arp", "live", "strong" },
new string[] { "lively", "alive", "harp", "sharp", "armstrong" });
var expected = new string[] { "arp", "live", "strong" };
CollectionAssert.AreEqual(expected, actual);
}
}
接下來就把程式提交,就可以看到美妙的綠燈亮出來啦
不過最重要的是在提交之後可以看見別人所寫的程式碼,其中有一個人寫的程式碼跟我的邏輯相同但他們以Linq的方式寫出來,也更精簡,如下
心得:
在這次的練習過稱中儘管不小心把Contains方法寫成Equal 也把 加入的字串a1 寫成 a2 還有 迴圈比較也寫反,但也因為後面的測試案例修改以及每一次的重新審視Production Code而及早發現程式碼發生的問題,所以覺得除了自己的測試案例還有進步的空間之外還有自己在寫Code的時候也要更加謹慎才能更有效率地把程式完成。
91在介紹codewars以及跟我私聊幾句時說了下面這段話
我們需要找到一種持續給自己回饋的方式,才能持續改善
所以 scrum 裡面有 iteration (迭代)
所以有 retrospective
一切都是持續改善的基本要素