Array
配列

注意事項

毎回の授業の最初に出席メールを提出せよ.

前回までの出席記録を確認せよ.出席メールを授業時間内に 送信したのに記載されていない学生はメールの自分宛のコピーを印刷し,宛先アドレス, 提出時間が間違っていないことを確認してから申し出よ.

入力フォーム例

7.4 節で学習する内容だが,入力フォームを使った例を挙げる. 入力を必要とするサンプル,課題に利用する.以下の例 12 はフォームに入力されたものをそのまま出力するスクリプトである.

例 12

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01//EN">
<html lang="ja">
  <head>
    <title>Sample of FORM</title>
  </head>

  <body>
    <form action="<?php echo $_SERVER['PHP_SELF']; ?>" method = "GET">
      Input: <input type="text" name="data" />
      <input type="submit" />
    </form>
    <p>
<?php
if(isset($_GET['data'])){
  $s = htmlentities($_GET['data']);
  echo "Output: $s";
}
?>
    </p>
  </body>
</html>

例題 6.1

例12 を変更し,整数の入力データの 2 倍の値を出力するスクリプトを作成せよ. 入力は必ず正の整数値であると仮定してよい.

5章 配列

5.1 インデックス配列と連想配列

php の配列はインデックス配列(C などの一般的な配列)と連想配列の 2 種類. 内部的にはどちらも連想配列として記憶している.インデックス配列はキーが 0 から始まる整数で, 配列名とキーの整数で特定の要素にアクセスする.(例: $shows[2] はインデックス配列 $shows の 3 番目の要素)連想配列では配列名と文字列のキー で特定の要素にアクセスする.(例: $age['Fred'] は連想配列 $age の,キー'Fred' で一意に決まる要素)連想配列でも要素の並び順は保持されている.

5.2 配列の要素の識別

連想配列のキー文字列は基本的には引用符で囲む.ただし,その配列変数が引用符の中に ある場合は引用符をつけない.

5.3 配列へのデータ格納

事前に配列のサイズ等を宣言しなくても,代入が起こるたびにスペースが作成される.

スペースが自動生成されることを利用して,特に事前の宣言なしに p.129 の例のように通常の代入文を書き連ねることで配列に要素を格納してゆくことができる.

格納するデータが大量にある場合は array() 構文が便利である.インデックスの 決まり方等を理解して使用すること.

インデックス配列の要素数をチェックしなくても配列名に [] をつけたものへ代入 することで自動的に末尾にスペースを作ってそこに格納してくれる.

range() を使って連続データを要素とする配列を作ることができる.

count() で配列の要素数を知ることができる.

例題 6.2

array() を使って適当な大きさのインデックス配列を作り, count() を使ってサイズを求めて表示するスクリプトを作成せよ.

array_pad() で指定した配列サイズまで配列スペースを確保し,開いている要素に 初期値を入れることができる.p.131 の 9,10 行め参照.

5.4 多次元配列

配列を配列に格納することができる.変数展開には{}記号を使う.

5.5 多次元配列の展開

list() を使って複数の変数に配列要素を順番に代入することができる.p.132 8,9 行目 参照.

array_slice() で配列の一部を切り出すことができる.p.132 下から 2,3 行目参照.

array_chunk() で大きな配列を複数の小さな配列に分割できる.分割された 複数の配列は,配列の配列として返り値となる.

array_keys()は連想配列のキーのみを内部的な順番で並べたインデックス配列を返す.

例えば連想配列 $person にキーが 'name' であるデータがあるかどうか知りたい場合, いきなり $person['name'] としてアクセスしてはいけない. この場合は array_key_exists('name', $person) でチェックする必要がある. p.135 最初の例は isset() と array_key_exists() の挙動を比較して理解するためのもの. 関数 tf() は引数が真なら "T", 偽なら "F" を返す関数で, このサンプルでは配列 $a は以下のようになっている.

a[0] 数値 0 が記憶されている
a[1] NULL データ型の唯一の値 NULL 値が記憶されている
a[2] 空文字列が記憶されている
a[3] インデックス 2 までしか生成されていない

array_splice() で配列の途中を削除して詰めたり,挿入したり,途中を削除した後,そこに データを挿入したりできる.

5.6 配列と変数の変換

extract() は連想配列から,キーを変数名とする変数群を作る.

compact() は extract() とは逆に変数群から連想配列を作る.

連想配列変数変数
$person['name']Fredextract($person)→$nameFred
$person['age']35←$person = compact('name', 'age', 'wife')$age35
$person['wife']Betty$wifeBetty

5.7 配列の順次処理

foreach の構文で,インデックス配列,連想配列どちらについても,全ての要素についての 処理を行うことができる.for と違って処理順は意識されないが,内部順序に基づいて処理される.

$addresses がインデックス配列のとき, foreach ($addresses as $value){ 処理 } でループ変数を $value として 処理される.最初に配列 $addresses[0] の値が $value にコピーされて処理され, 次に $addresses[1] の値がコピーされて処理され…という計算を $addresses の要素全てについて行う.

$person が連想配列のとき, foreach ($parson as $key => $value){ 処理 } で,キー用のループ変数を $key, 対応する値用のループ変数を $value として 処理される.最初に配列 $person の内部順序の最初の組についてキーが $key, 対応するの値が $value にコピーされて処理され, 次の内部順序の組についてキーが $key, 対応するの値が $value にコピーされて処理され…という計算を $person の要素全てについて行う.

each() などのイテレータ関数を利用して foreach と似た処理ができる. 例えば p.139 7 行目から始まる例は foreach と似た処理を行うが,値のコピーを行わない ことが特徴である.

インデックス配列に対しては C と同様な for 文による処理が行える.

foreach を使って配列の全ての内容についてそれを引数にユーザ定義関数を呼び出す処理を array_walk() で行うことができる.array_walk からの呼出しに適合するように, ユーザ定義関数を作る必要がある.ユーザ定義関数の第1引数には要素の値,第2引数には キーが渡される前提で関数を作成する.

array_reduce()は配列について総計を計算するための関数.

in_array() はある値が配列内にあるかどうかを調べる関数. array_search() はある値が配列内にあったときに true を返す代わりにその要素のキーを返す.

例題 6.3

入力フォームを使い,正の整数値をカンマで 区切った文字列が 入力されると仮定する.入力を explode 関数(p.101)を使って配列に分解し, count を使って配列の要素数を調べ,入力された値の個数を表示するスクリプト を作成せよ.

例題 6.4

例題 6.3 を修正する.分解された入力データを格納している配列変数 の要素すべてをループを使って出力するスクリプトを作成せよ. for を使用したものと foreach を使用したもの両方を作成せよ.

ヒント

以下のスクリプトで,

  1. 文字列 $s に入力全体を格納し,
  2. explode 関数を使用して 配列 $inputs に入力の各値を格納し,
  3. count 関数を使用して入力されたデータの個数を求め,
  4. 入力の 1個目, 2個目, 3個目を順に出力する

ことができる.$inputs は単純な変数ではなく配列であることに 注意せよ.

if(isset($_GET['data'])){
  $s = htmlentities($_GET['data']);
    $inputs = explode(',',$s);
    $num = count($inputs);
    echo "$inputs[0] ";
    echo "$inputs[1] ";
    echo "$inputs[2] ";
}

配列 $inputs のインデックス指定に変数 $i を使い, 以下のように書いても同じ動作をする.

if(isset($_GET['data'])){
  $s = htmlentities($_GET['data']);
    $inputs = explode(',',$s);
    $num = count($inputs);
    $i = 0;
    echo "$inputs[$i] ";
    $i = 1;
    echo "$inputs[$i] ";
    $i = 2;
    echo "$inputs[$i] ";
}

これを for ループで書いくと以下のようになる.

if(isset($_GET['data'])){
  $s = htmlentities($_GET['data']);
    $inputs = explode(',',$s);
    $num = count($inputs);
    for ($i = 0 ; $i <= 2 ; $i++){
      echo "$inputs[$i] ";
    }
}

このままでは入力された要素数が 3 個のときしか正しく動作しない. 入力された要素数は count 関数を使用して $num に求められているので $num を使ってループの終了条件を指定すれば任意の入力に 対応できる.最終インデックスが要素数 -1 であることに注意せよ.

if(isset($_GET['data'])){
  $s = htmlentities($_GET['data']);
    $inputs = explode(',',$s);
    $num = count($inputs);
    for ($i = 0 ; $i <= $num -1 ; $i++){
      echo "$inputs[$i] ";
    }
}

5.8 配列のソート

組込みで p.143 表 5-1 のような種々のソートが用意されている.

ソートアルゴリズムは組込みのものを使いたいが,大小関係の定義だけ 独自なものを使用したい場合が多くある.usort() を使う事でそれが可能になる. 任意の名前でユーザー定義の大小関係比較関数を作ってもよいが,入出力の 仕様が決められている.第 1 引数と第 2 引数が比較対象で,第 1 引数のほうが 大きいと判定するときは 1 を,小さいと判定するときは -1 を,等しいと判定するときは 0 を返すように作る.usort 関数にはソートすべき配列とユーザ定義の比較関数の名前を渡す.

5.9 配列全体に対する処理

配列の和を計算する array_sum(), 2 つ以上の配列をマージする array_marge(), 配列の差を求める array_diff(), ユーザ定義のフィルタ関数の判定に基づいて フィルタリングを行う array_filter() 関数が利用できる.

5.10 配列の使用法

配列を集合とみなして種々の集合演算ができる.array_marge(), array_unique() を使って和集合を計算できる.array_intersect() で積集合を求めることができる.

データをつねに末尾に挿入し,取り出しもつねに末尾からに制限されるデータ構造を スタックという.スタック操作専用の関数 array_pop() と array_push() がある.

第 5 回課題「配列の順次処理」 を提出せよ.


Updated in May 19, 2009, index.html, Yamamoto Hiroshi