「Foreach文」の版間の差分
255行目: | 255行目: | ||
SELECT文でとってきた複数レコードを、カーソルを使って順繰り出力するPL/SQL文を示す。 |
SELECT文でとってきた複数レコードを、カーソルを使って順繰り出力するPL/SQL文を示す。 |
||
< |
<syntaxhighlight lang="sql"> |
||
DECLARE |
DECLARE |
||
CURSOR C IS |
CURSOR C IS |
||
269行目: | 269行目: | ||
END LOOP; |
END LOOP; |
||
END; |
END; |
||
</syntaxhighlight> |
|||
</source> |
|||
== 関連項目 == |
== 関連項目 == |
2020年7月6日 (月) 00:29時点における版
foreach文(フォーイーチぶん)とはプログラミング言語においてリストや連想配列などの「コレクション」と呼ばれるデータ構造の各要素に対して与えられた文の実行を繰り返すというループを記述するための文である。foreach文はしばしばfor文の一部という位置付けにある。for文と異なり要素の参照順序が定義されないこともある。
処理の流れ
基本的な構文 (Perl) は以下のようになる。
foreach 変数 (リスト) {
文
}
このループはだいたい次のような手順で実行される。
- 変数にリストの中のある要素への参照を代入する。
- 文を実行する。
- リストの全要素を参照し終わっていない場合は、変数に未参照の要素を代入して文の実行へ戻る。
ここで、線形リストや配列など要素の順序が決まっているものは、通常その順序でループが実行されるので、この場合以下とほぼ同様である。
for ( my $i = 0; $i < @list; $i++ ) {
変数 = $list[$i];
文
}
ただし、ハッシュテーブル(連想配列)については要素の順序関係が決定できないこともあるため、一般に参照順序は不定である。
文法
awkにおいても連想配列の処理を可能にしている。
for (変数 in 配列)
{
文
}
foreach (変数 in コレクション)
{
文
}
コレクションは配列のほか、IEnumerableもしくはIEnumerable<T>を実装したオブジェクトでもよい。
C++は、2011年での規格改定(通称C++11)にて、範囲ベースの for ループが言語仕様として追加されている。
for (変数 : コレクション)
{
文
}
上記で「コレクション」と記した箇所には、配列のほか、std::vectorやstd::arrayのような標準ライブラリにおいてコンテナに分類される各種のオブジェクトなども使用できる。
そのほか、1998年の標準規格化当初からC++標準ライブラリにfor_eachアルゴリズム(関数テンプレート)が存在する。
関数オブジェクト = std::for_each(
先頭イテレータ,
末尾イテレータ,
関数オブジェクト
);
C++11では、C#同様に型推論およびラムダ式を組み合わせることで、上記の構文が威力を発揮するようになる。
なお、C++/CLI言語およびMicrosoft Visual C++ 2005以降の独自拡張機能では、for each
文を使用できるが、不安定で正常に動作しない場合がある[要説明]。また、これはC++11における範囲ベース for ループとは互換性を持たない。
for each (変数 in コレクション)
{
文
}
式を評価し、その結果は静的配列、動的配列、連想配列、構造体、クラスでなければいけない。式部分が配列である場合は、変数は複数宣言することができる。
foreach (変数 ; 式) {
文
}
Java 5.0以降
拡張For文などと呼び、Java 5.0 で導入された。For文の特殊なものとして捉えられるが、Foreach文に相当する。
for (変数 : コレクション) {
文
}
オブジェクトの反復処理にはfor-in文を用いる。変数にはプロパティ名(連想配列で言うキー)が代入されるので、プロパティの値は式 オブジェクト[変数]
で取得する。
for (var 変数 in オブジェクト) {
文
}
JavaScriptのfor-in文は、ユーザー定義のプロパティについて、プロトタイプチェーンをさかのぼって反復処理を行う。このため、特に配列に対してfor-in文を用いると、他の言語とは異なる挙動をすることがある。
var array = new Array(3);
var output = "";
for (var key in array) { output += key + " "; }
// このとき array.length === 3 であるが、
// array にユーザー側からプロパティ(配列要素)を定義していないので、
// output === "" である。
// 配列もオブジェクトなので、数値以外のプロパティを設定できる。
array.foo = "foo"
output = "";
for (var key in array) { output += key + " "; }
// このとき output === "foo " である。
// オブジェクトに新しいインスタンスメソッドを追加してみる。
Object.prototype.myMethod = function () {};
output = "";
for (var key in array) { output += key + " "; }
// 配列もオブジェクトなので、このとき output === "foo myMethod " である。
// なおもちろん、この時点でも array.length === 3 である。
ECMA-262第5版 (JavaScript 1.6, ActionScript 3.0) からは、ArrayインスタンスにforEachメソッドが追加された。
array.forEach(function (変数) {
文
});
ECMA-262第6版からは、配列などのiterableオブジェクトの値で反復処理をするfor-of文も導入された。
for (変数 of オブジェクト) {
文
}
しばしばforが代用とされる。Perlにおいて、forとforeachは同義語である。
foreach 変数 (コレクション) {
文
}
foreach (配列 as 変数) {
文
}
foreach (配列 as 変数1 => 変数2) {
文
}
前者の場合、処理手順は他の言語と同様だが、後者の場合、変数1に配列の添字が、変数2に要素が代入される。
PythonにおけるFor文とは、他の言語におけるForeach文と同等である。
for 変数 in コレクション :
文
for 変数 in コレクション
文
end
これは以下のイテレータ構文と、変数のスコープを除いて等価である。
コレクション.each do |変数|
文
end
なお、Rubyに関してはもっぱら後者の構文が好まれる傾向にある。
コレクション do:
[ :変数 |
文
].
SmalltakはLispの影響を受けており、言語構文として反復構文が存在せず、#do:セレクターとブロックオブジェクトを使ったメッセージで表現する。上記ではメッセージを受け取るレシーバーをコレクションと表記しているが、#do:は下記の条件を満たしていれば良く、入力ストリームや0回か1回しか実行しないオブジェクト、無限数列などもレシーバーとして指定できる。また、#do:のために反復状態を持つ専用のクラスが必要なく#do:のメソッドだけで完結するため、C++のような方式に比べ実装が単純になっている。またフィルターも容易であり、フィルター用のクラスも多数存在する。#do:は列挙プロトコルに属しており、#do:を実装しCollectionあるいはIterableを継承したオブジェクトは、#select:, #collect:, #detect:, #inject:into:といったその他の列挙プロトコルが同時に使えるようになる。
- 戻り値を返さない。(Smalltalkの制約上、正確にはselfを返す)
- #do:の引数としてValueAdapter (#value:を送ることができるオブジェクト) を指定する。(ブロックはValueAdapterの一種)
- 引数として指定したValueAdapterが0回以上の反復に対応している。
(1 to: 100) do:
[ :each |
文
].
例えば一定回数反復したい場合も#do:を使い、上記のようになる。
Smalltalkは後発の無名関数を備えたオブジェクト指向言語に広く影響を与えており、Ruby、ECMAScript、Java、C#も同様のライブラリを備えつつある。
For Each 変数 In コレクション
文
Next 変数
foreach (変数 in コレクション) {
文
}
foreach 変数 文 loop
(リスト)を反復。 文
変数は「それ」に代入される。
cshではforeachと書き、shではforと書く。実用上リストの部分にはワイルドカードを含むファイル列を書くことが多い。
csh系
foreach 変数 ( リスト )
文
end
sh系
for 変数 in リスト
do
文
done
番外編
OracleのPL/SQLにも、カーソルというForEachと似たような機能が実装されている。 カーソルは用途が限定されているため、番外編として紹介する。
SELECT文でとってきた複数レコードを、カーソルを使って順繰り出力するPL/SQL文を示す。
DECLARE
CURSOR C IS
SELECT
*
FROM
TBL1
WHERE
TBL1.FIELD1 >= 100;
BEGIN
FOR D IN C LOOP
DBMS_OUTPUT.PUT_LINE(D.FIELD1 || ' ' || D.FIELD2 || ' ' || D.FIELD3);
END LOOP;
END;