4D v18

For each...End for each

ホーム

 
4D v18
For each...End for each

For each...End for each  


 

 

For each...End for each のコントロールフローストラクチャーの正式なシンタックスは、以下のようになります:

 For each(Current_Item;Expression{;begin{;end}}){Until|While}(Boolean_Expression)}
    statement(s)
 End for each

For each...End for each ストラクチャーは、Expression 引数の全ての値に対してCurrent_item 引数で指定された項目を繰り返します。Current_item 引数の型は、Expression 引数の型に依存します。For each...End for each ループは3つのExpression 引数の型に対して繰り返しをします:

  • コレクション: コレクションの各要素をループ
  • エンティティセレクション: 各エンティティをループ
  • オブジェクト: 各オブジェクトプロパティをループ

以下の表は、For each...End for each の3つのタイプを比較したものです:

コレクション内をループエンティティセレクション内をループオブジェクト内をループ
Current_Item 引数の型コレクション要素と同じ型の変数エンティティテキスト変数
Expression 引数の型コレクション(同じ型の要素)エンティティセレクションオブジェクト
ループ数(デフォルト)コレクションの要素数セレクション内のエンティティ数オブジェクトのプロパティ数
begin / end 引数のサポートサポートするサポートするサポートしない
  • ループの数はスタートアップ時に評価され、処理中に変化することはありません。ループ中に項目を追加・削除することは、繰り返しの不足・重複を引き起こすことがあるため、一般的には推奨されません。
  • デフォルトでは、内部のstatement(s) 部分の処理は、Expression引数の各値に対して実行されます。しかしながら、ループの先頭(While)あるいはループの終わり(Until)である条件をテストすることで、ループを抜け出すことは可能です。
  • 任意のbegin および end 引数を使用することで、コレクションおよびエンティティセレクションに対してループの限度を定義することができます。

For each...End for eachCollection 型のExpression 引数に対して使用された場合、Current_Item 引数はコレクション要素と同じ型の変数です。デフォルトでは、ループの回数はコレクションの項目数に基づいています。

コレクションは同じ型の要素しか含んではいけません。そうでない場合には、Current_Item 変数に他の型の値が代入されたときにエラーが生成されます。

各ループの繰り返しにおいて、Current_Item 変数には、合致するコレクションの要素が自動的に代入されます。このとき、以下の点に注意する必要があります:

  • Current_Item 変数がオブジェクト型あるいはコレクション型であった(つまり引数がオブジェクトのコレクション、あるいはコレクションのコレクションであった)場合、この変数を変更すると自動的にコレクションの合致する要素も変更されます(オブジェクトとコレクションは同じ参照を共有しているからです)。変数がスカラー型である場合、変数のみが変更されます。
  • Current_Item 変数は、コレクション要素の型と合致している必要があります。コレクションの項目に、どれか一つでも変数と異なる型のものがあった場合、エラーが生成され、ループは停止します。
  • コレクションがNull 値の要素を格納していたとき、Current_Item 変数の型がNull 値をサポートしない型(例えば倍長整数変数など)であった場合にはエラーが生成されます。
例題  

数値のコレクションに対して、統計情報を計算したい場合を考えます:

 C_COLLECTION($nums)
 $nums:=New collection(10;5001;6665;33;1;42;7850)
 C_LONGINT($item;$vEven;$vOdd;$vUnder;$vOver)
 For each($item;$nums)
    If($item%2=0)
       $vEven:=$vEven+1
    Else
       $vOdd:=$vOdd+1
    End if
    Case of
       :($item<5000)
          $vUnder:=$vUnder+1
       :($item>6000)
          $vOver:=$vOver+1
    End case
 End for each
  //$vEven=3, $vOdd=4
  //$vUnder=4,$vOver=2

For each...End for eachEntity selection 型のExpression 引数に対して使用された場合、Current_Item 引数は現在処理されているエンティティです。

ループの回数はエンティティセレクション内のエンティティの数に基づいています。各ループの繰り返しにおいて、Current_Item 引数には、現在処理されているエンティティセレクション内のエンティティが自動的に代入されます。

注: エンティティセレクションに、途中で他のプロセスによって削除されたエンティティが含まれていた場合、そのエンティティはループにおいて自動的にスキップされます。

カレントエンティティに対して行われた適用された変更は、entity.save( ) を使用して明示的に保存する必要があることに注意してください。

例題  

エンティティセレクション内の英国の従業員の給与を引き上げたい場合を考えます:

 C_OBJECT(emp)
 For each(emp;ds.Employees.query("country='UK'"))
    emp.salary:=emp.salary*1,03
    emp.save()
 End for each

For each...End for eachObject 型のExpression 引数に対して使用された場合、Current_Item 引数は現在処理されているプロパティ名が自動的に代入されているテキスト変数です。

オブジェクトのプロパティは作成順に処理されていきます。ループ中、プロパティをオブジェクトに追加/削除することが可能ですが、その場合でも残りのループ回数は、オブジェクトの元のプロパティ数に基づいているため、変化しません。

例題  

以下のオブジェクトにおいて、名前を全て大文字に変えたい場合を考えます:

{
    "firstname": "gregory",
    "lastname": "badikora",
    "age": 20
}

以下のように書くことができます:

 For each(property;vObject)
    If(Value type(vObject[property])=Is text)
       vObject[property]:=Uppercase(vObject[property])
    End if
 End for each

{
    "firstname": "GREGORY",
    "lastname": "BADIKORA",
    "age": 20
}

任意のbeginend 引数を使用することで、繰り返しに制限を定義することができます。

注: beginend 引数は、コレクションおよびエンティティセレクション型に対する繰り返しにおいてのみ使用することができます(オブジェクトプロパティのときには無視されます)。

  • begin 引数には、Expression 引数内の繰り返しの開始を指定したい要素位置を渡します(このときbegin の値は含まれます)。
  • end 引数には、Expression 引数内の繰り返しの終了を指定したい要素位置を渡します(このときend の値は含まれません)。

end 引数が省略されている、あるいはend 引数がExpression 引数の要素数より大きい場合、begin 引数の位置から最後の要素まで(含まれる)が繰り返されます。

beginend 引数が正の値の場合、それらはExpression 引数内の要素の実際の位置を表します。

begin 引数が負の値の場合、それはbegin:=begin+Expression のサイズ として再計算されます(Expression 引数の終端からのオフセットであるとみなされます)。再計算された値も負の値だった場合、begin 引数は0に設定されます。
注: begin 引数が負の値だったとしても、繰り返しそのものは標準の順番で実行されます。
引数が負の値だった場合、それはとしてend:=end+Expression のサイズ として再計算されます。

例:

  • コレクションには10個の要素が格納されている(ナンバリングは0から9)
  • begin=-4 -> begin=-4+10=6 -> 繰り返しは6番目の要素(#5)から開始される
  • end=-2 -> end=-2+10=8 -> 繰り返しは8番目の要素(#7)の前に終了する、つまり7番目の要素で終了
例題  

 C_COLLECTION($col;$col2)
 $col:=New collection("a";"b";"c";"d";"e")
 $col2:=New collection(1;2;3)
 C_TEXT($item)
 For each($item;$col;0;3)
    $col2.push($item)
 End for each
  //$col2=[1,2,3,"a","b","c"]
 For each($item;$col;-2;-1)
    $col2.push($item)
 End for each
  //$col2=[1,2,3,"a","b","c","d"]

For each...End for each の実行は、Until あるいは While 条件をループに追加することでコントロールすることができます。Until(condition) あるいは While(condition) 宣言がループに組み込まれた場合、繰り返しはcondition 引数がtrue に評価されると停止します。

必要に応じて、以下の二つのキーワードのいづれかを渡すことができます:

  • Until 条件は各繰り返しの最後にテストされます。ですからExpression 引数が空あるいはnull ではなければ、ループは少なくとも1回は実行されます。
  • While 条件は各繰り返しの最初にテストされます。ですから条件の結果次第では、ループは一度も実行されないことも有り得ます。
例題  

 $colNum:=New collection(1;2;3;4;5;6;7;8;9;10)
 
 $total:=0
 For each($num;$colNum)While($total<30) //最初にテストされる
    $total:=$total+$num
 End for each
 ALERT(String($total)) //$total = 36 (1+2+3+4+5+6+7+8)
 
 $total:=1000
 For each($num;$colNum)Until($total>30) //最後にテストされる
    $total:=$total+$num
 End for each
 ALERT(String($total)) //$total = 1001 (1000+1)

For each...End for each ループは、共有コレクションおよび共有オブジェクトに対しても使用することができます。

コードがコレクションあるいはオブジェクトプロパティの一つ以上の要素を変更する必要がある場合、Use...End use キーワードを使用する必要があります。必要に応じて、Use...End use キーワードを以下の二つの場所で使用することができます:

  • 統合性の観点から項目が編集された方がいい場合には、ループに入る前に使用
  • 一部の要素/プロパティのみを編集する必要があり統合性の管理が必要ない場合には、ループ内部で使用

 
プロパティ 

プロダクト: 4D
テーマ: プログラミング言語の構成要素

 
ページの目次 
 
履歴 

初出: 4D v17

 
ARTICLE USAGE

ランゲージリファレンス ( 4D v18)