循環取出IEnumerable中的元素

  • 330
  • 0

循環取出IEnumerable中的元素

給定一個IEnumerable<T> pattern與int length,如何循環取出pattern中的元素直到數量達到length?

先上第一版的code:

	int length = 8;
	var pattern = new string[] { "a", "b", "c" };
	
	List<string> result = new List<string>();
	while (result.Count < length)
		result.Add(pattern[result.Count % pattern.Length]);

result為最後結果,在迴圈執行中將pattern的元素加入result

由於每次加入元素後result.Count會增加,可以用result.Count作為取得下一個pattern的index的計數器

接著考慮計數器的值>=pattern.Length的狀況,因為是循環取,index超過時要重新回到pattern的頭,如此index可表示為result.Count % pattern.Length

結果也是符合預期的,依序循環取出{ "a", "b", "c" }的元素直到長度為8,只是還是會想著又是Count又是Length還要取餘數,有沒有比較好懂的方式?

這個情境在codewars時遇到

第一版寫完後看了一下其他人的做法,看到一個感覺不錯的方法(之後再改寫了一下但意義上與原方法相同):

public static IEnumerable<T> RepeatCyclical<T>(this IEnumerable<T> src)
{
    while (true)
    {
        foreach (var item in src)
            yield return item;
    }
}

執行結果:

雖然循環取得pattern也許不是codewars題目重心,但這個方法還是不錯的

看似一個無窮迴圈,使用LazyExecute特性配上後面的Take(length)就限制了其次數,不用自己處理計數器、取餘數等操作,也把取pattern的抽象概念獨立出來了

這個codewars題目本身也很有趣,取得pattern後只是決定了這次輸出的算法,之後算法的實作都要自己來,感覺還有點設計模式的味道

原題連結:http://www.codewars.com/kata/5811aef3acdf4dab5e000251