for…の場合の配列の反復の置換
質問
私は Python のリスト内包表記が大好きです。リストの内包表記はリストの変換を簡潔に表すからです。
ただし、他の言語では、次のようなことを書いていることがよくあります。
foreach (int x in intArray)
if (x > 3) //generic condition on x
x++
//do other processing
この例は C# で書かれています。LINQ がこれに役立つと思いますが、このややエレガントとは言えないソリューションを置き換えることができる一般的なプログラミング構造はあるのでしょうか?おそらく私が考慮していないデータ構造でしょうか?
解決
オリジナルの増分 foreach
ループは配列の内容に影響を与えません。これを行う唯一の方法は依然として for
ループ:
for(int i = 0; i < intArray.Length; ++i)
{
if(intArray[i] > 3) ++intArray[i];
}
Linq は、既存のコレクションやシーケンスを変更することを目的としたものではありません。既存のシーケンスに基づいて新しいシーケンスを作成します。Linq を使用して上記のコードを実現することは可能ですが、目的とは少し異なります。
var newArray1 = from i in intArray select ((i > 3) ? (i + 1) : (i));
var newArray2 = intArray.Select(i => (i > 3) ? (i + 1) : (i));
使用する where
(または同等の) は、他の回答の一部に示されているように、結果のシーケンスから 3 以下の値を除外します。
var intArray = new int[] { 10, 1, 20, 2 };
var newArray = from i in intArray where i > 3 select i + 1;
// newArray == { 11, 21 }
があります ForEach
配列のメソッドを使用すると、ラムダ関数の代わりにラムダ関数を使用できるようになります。 foreach
ブロックしますが、メソッド呼び出し以外の場合はブロックします。 foreach
.
intArray.ForEach(i => DoSomething(i));
他のヒント
C# では、次のように IEnumerable 内にあるものすべてに選択的な処理を適用できます。
intArray.Where(i => i > 3).ConvertAll();
DoStuff(intArray.Where(i => i 3));
等..
Rubyでは:
intArray.select { |x| x > 3 }.each do |x|
# do other processing
end
または、「その他の処理」が短いワンライナーの場合:
intArray.select { |x| x > 3 }.each { |x| something_that_uses x }
最後に、3 より大きい要素の処理結果を含む新しい配列を返したい場合は、次のようにします。
intArray.select { |x| x > 3 }.map { |x| do_something_to x }
map(lambda x: test(x + 1) filter(lambda x: x > 3, arr))
言語と何をする必要があるかによって異なりますが、多くの言語で「マップ」と呼ばれるものが探しているものになる可能性があります。C#は分かりませんが、によると これ ページでは、.NET 2.0 はマップを「ConvertAll」と呼びます。
「マップ」の意味は非常に単純です。リストを取得し、その各要素に関数を適用して、新しいリストを返します。また、別のリストの述語を満たす項目のリストを提供する「フィルター」を探している場合もあります。