var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> { 1, 2, 3 };
一連の結果「a1」、「b2」、「c3」を生成する両方を反復処理するための最もエレガントな方法は何ですか?
var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> { 1, 2, 3 };
一連の結果「a1」、「b2」、「c3」を生成する両方を反復処理するための最もエレガントな方法は何ですか?
これは、2つのシーケンスの「zip」または「zip結合」として知られています。Eric Lippertは、まさにこのアルゴリズムについて説明し、実装を提供します。
強力なBartdeSmetがzip関数についてここで説明しています:
彼の最も洗練されたソリューションは、パラメーターとして2パラメーターのFuncデリゲートを使用するselectのオーバーロードを利用しています。
a.Select((t,i)=>new{t,i});
この例では、iは単に処理中のアイテムのインデックスを表します。したがって、これらの匿名オブジェクトの2つの新しい列挙可能オブジェクトを作成し、それらをiに結合できます。
パフォーマンスに関しては、より明白な降伏ループを使用します。
EricとBartによるすばらしい投稿を補足するために、System.Linq3.5演算子を使用した実装を次に示します。
public static IEnumerable<TResult> Zip<TFirst, TSecond, TResult> (
this IEnumerable<TFirst> first,
IEnumerable<TSecond> second,
Func<TFirst, TSecond, TResult> resultSelector)
{
return from aa in a.Select((x, i) => new { x, i })
join bb in b.Select((y, j) => new { y, j })
on aa.i equals bb.j
select resultSelector(aa.x, bb.y);
}
これをエレガントに処理するイテレータブロックを作成できます。
public static class Ext
{
public static IEnumerable<string> ConcatEach(this IEnumerable a,
IEnumerable b)
{
var aItor = a.GetEnumerator();
var bItor = b.GetEnumerator();
while (aItor.MoveNext() && bItor.MoveNext())
yield return aItor.Current.ToString() + bItor.Current;
}
}
エレガントに呼んでください=)次のように:
var a = new Collection<string> {"a", "b", "c"};
var b = new Collection<int> {1, 2, 3};
foreach(var joined in a.ConcatEach(b))
{
Console.WriteLine(joined);
}