今回は、Zip拡張メソッドについてです。
この拡張メソッドは、.NET 4.0で追加されました。
Zip拡張メソッドは、簡単に言うと、2つのシーケンスを同時にループしてくれる拡張メソッドです。
Pythonのzip関数と同じです。
これを利用すると、複数のシーケンスをループする際にシンプルに記述出来たりします。
書式は以下の通り。
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult>( this IEnumerable<TFirst> first, IEnumerable<TSecond> second, Func<TFirst, TSecond, TResult> resultSelector )
resultSelectorにて、結果のデータを決定します。
引数には、(一つ目のシーケンスの現在の要素, 2つ目のシーケンスの現在の要素)が渡されます。
Zip拡張メソッドには、ひとつだけ注意点があります。
MSDNにも記述されているのですが、このメソッドは
どちらかのシーケンスの要素が終わるまで、処理を続ける.
という動きになっています。
なので、2つのシーケンスの要素数が異なる場合、要素数が少ない方のシーケンス分だけ
ループされます。
以下、サンプルです。
#region LinqSamples-36 public class LinqSamples36 : IExecutable { public void Execute() { // // Zip拡張メソッド. // // Zip拡張メソッドは、Pythonのzip関数と同じ動きをするものである。 // つまり、2つのシーケンスを同時にループさせることが出来る。 // // 第二引数には、resultSelectorを指定する必要があり、好きなデータを返す事ができる。 // // このメソッドは、どちらかのシーケンスが終わるまで処理を続けるという仕様になっているので // 2つのシーケンスの要素数が異なる場合は、注意が必要である。 // // つまり、片方のシーケンスが空の場合、このメソッドは一度もループされない。 // IEnumerable<int> numbers1 = new int[]{ 1, 2, 3, 4, 5 }; IEnumerable<int> numbers2 = new int[]{ 6, 7, 8, 9, 0 }; var query = numbers1.Zip(numbers2, (first, second) => Tuple.Create(first, second)); Console.WriteLine("========= 2つのシーケンスの要素数が同じ場合 ==========="); foreach (var item in query) { Console.WriteLine("FIRST={0}, SECOND={1}", item.Item1, item.Item2); } numbers1 = new int[]{ 1, 2, 3 }; numbers2 = new int[]{ 6, 7, 8, 9, 0 }; query = numbers1.Zip(numbers2, (first, second) => Tuple.Create(first, second)); Console.WriteLine("========= 1つ目のシーケンスの要素が2つ目よりも少ない場合 ==========="); foreach (var item in query) { Console.WriteLine("FIRST={0}, SECOND={1}", item.Item1, item.Item2); } numbers1 = new int[]{ 1, 2, 3, 4, 5 }; numbers2 = new int[]{ 6, 7, 8 }; query = numbers1.Zip(numbers2, (first, second) => Tuple.Create(first, second)); Console.WriteLine("========= 2つ目のシーケンスの要素が1つ目よりも少ない場合 ==========="); foreach (var item in query) { Console.WriteLine("FIRST={0}, SECOND={1}", item.Item1, item.Item2); } numbers1 = Enumerable.Empty<int>(); numbers2 = new int[]{ 6, 7, 8 }; query = numbers1.Zip(numbers2, (first, second) => Tuple.Create(first, second)); Console.WriteLine("========= どちらかのシーケンスが空の場合 ==========="); foreach (var item in query) { Console.WriteLine("FIRST={0}, SECOND={1}", item.Item1, item.Item2); } } } #endregion
実行結果は以下の通りです。
========= 2つのシーケンスの要素数が同じ場合 =========== FIRST=1, SECOND=6 FIRST=2, SECOND=7 FIRST=3, SECOND=8 FIRST=4, SECOND=9 FIRST=5, SECOND=0 ========= 1つ目のシーケンスの要素が2つ目よりも少ない場合 =========== FIRST=1, SECOND=6 FIRST=2, SECOND=7 FIRST=3, SECOND=8 ========= 2つ目のシーケンスの要素が1つ目よりも少ない場合 =========== FIRST=1, SECOND=6 FIRST=2, SECOND=7 FIRST=3, SECOND=8 ========= どちらかのシーケンスが空の場合 ===========
================================
過去の記事については、以下のページからご参照下さい。
- いろいろ備忘録日記まとめ