PHPを使うなら理解しておきたいアルゴリズム - 抽出・ソート・結合・集計
説明に使用するデータ構造
アルゴリズムの説明のために、以下のような配列の配列を使います。
$countries = array(); $countries= array( name => "日本", currency => "JPY", population => 127156000 ); $countries= array( name => "フランス", currency => "EUR", population => 65073482 ); $countries= array( name => "スペイン", currency => "EUR", population => 44904000 ); $countries= array( name => "ロシア", currency => "RUB", population => 141903979 ); $countries= array( name => "ベトナム", currency => "VND", population => 84238000 ); $countries= array( name => "カンボジア", currency => "KHR", population => 14805000 ); $countries[]= array( name => "コートジボワール", currency => "XOF", population => 44904000 );
この配列の配列の内容は、以下のようなコードでブラウザに表示できます。
print( "<table border='1'>" ); // テーブルヘッダを出力する。 print( "<tr>" ); print( "<th>国名</th>" ); print( "<th>通貨</th>" ); print( "<th>人口</th>" ); print( "</tr>" ); for ( $i = 0; $i < count( $countries ); ++$i ) { $country = $countries[$i]; // テーブルデータを出力する。 print( "<tr>" ); print( "<td>" . $country["name"] . "</td>" ); print( "<td>" . $country["currency"] . "</td>" ); print( "<td>" . $country["population"] . "</td>" ); print( "</tr>" ); } print( "</table>" );
このコードの実行結果は以下の通りです。
国名 | 通貨 | 人口 |
---|---|---|
日本 | JPY | 127156000 |
フランス | EUR | 65073482 |
スペイン | EUR | 44904000 |
ロシア | RUB | 141903979 |
ベトナム | VND | 84238000 |
カンボジア | KHR | 14805000 |
コートジボワール | XOF | 44904000 |
■抽出
複数のデータの中から、特定の条件を満たすデータを抽出するアルゴリズムです。
例として、商品データproductsから特定の条件を満たすデータを抽出します。
$products = array(); $products = array( product_id => "1010", product_name => "えんぴつ", price => 80 ); $products = array( product_id => "1020", product_name => "ボールペン", price => 100 ); $products = array( product_id => "1030", product_name => "消しゴム", price => 100 ); $products = array( product_id => "2010", product_name => "定規", price => 140 ); $products = array( product_id => "2020", product_name => "コンパス", price => 300 ); $products = array( product_id => "3010", product_name => "のり", price => 200 );
商品データproductsをブラウザに表示すると、以下のようになります。
商品ID | 商品名 | 価格 |
---|---|---|
1010 | えんぴつ | 80 |
1020 | ボールペン | 100 |
1030 | 消しゴム | 100 |
2010 | 定規 | 140 |
2020 | コンパス | 300 |
3010 | のり | 200 |
以下のコードは、商品データproductsから「price > 100」を満たすデータを抽出します。
// 抽出結果を格納する配列 $results = array(); // すべての商品データについて繰り返す。 for ( $i = 0; $i < count( $products ); ++$i ) { $product = $products[$i]; // 商品データのpriceが100より大きいことを確認する。 if ( $product["price"] > 100 ) { // 商品データを抽出結果に追加する。 $results[]= $product; } }
抽出結果は、変数resultsに格納されます。抽出結果resultをブラウザに表示すると、以下のようになります。
商品ID | 商品名 | 価格 |
---|---|---|
2010 | 定規 | 140 |
2020 | コンパス | 300 |
3010 | のり | 200 |
■ソート
複数のデータを、特定の条件でソートするアルゴリズムです
PHPでの配列のソート
ソートの例の前に、PHPでの配列のソートについて説明します。
配列をソートするには、usort()関数を使用します。
$array = array( 13, 43, 22, 234 ); usort( $array, "comp" ); function comp( $a, $b ) { // 引数1と引数2はそれぞれ配列中の値。 // 引き算により引数の大小を比較する。 // ・引数2の方が大きければ、戻り値は正の値: 引数2→引数1の順に並ぶ。 // ・引数同士が一致すれば、戻り値は0: 引数1と引数2は同列。 // ・引数1の方が大きければ、戻り値は負の値: 引数1→引数2の順に並ぶ。 return $b - $a; }
ソートの並び順は、usort()メソッドの引数に渡す比較関数で決めます。比較関数は通常のユーザ定義関数と同様に定義し、その比較関数の名前をusort()メソッドの引数に渡します。
比較関数には引数として配列の要素が2つずつ渡されます。引数2→引数1の順に並べたい場合は正の値を、引数1と引数2を同列にしたい場合は0を、引数1→引数2の順に並べたい場合は負の値を、比較関数の戻り値として返します。
なお、上記のコードは配列の要素を「数値の降順」にソートします。
ソートの例(五十音順)
それでは、ソートの例を挙げます。
例として、売上データsalesを特定の項目の「五十音順」にソートします。
$sales = array(); $sales = array( sales_date => "20090702" , sales_no => "00001" , product_id => "1020" , amount => 10 ); $sales = array( sales_date => "20090702" , sales_no => "00002" , product_id => "1010" , amount => 5 ); $sales = array( sales_date => "20090702" , sales_no => "00003" , product_id => "3010" , amount => 20 ); $sales = array( sales_date => "20090703" , sales_no => "00001" , product_id => "1030" , amount => 10 ); $sales = array( sales_date => "20090703" , sales_no => "00002" , product_id => "1020" , amount => 15 ); $sales = array( sales_date => "20090704" , sales_no => "00001" , product_id => "2020" , amount => 30 ); $sales[] = array( sales_date => "20090704" , sales_no => "00002" , product_id => "3010" , amount => 20 );
売上データsalesをブラウザに表示すると、以下のようになります。
売上日 | 売上番号 | 商品ID | 数量 |
---|---|---|---|
20090702 | 00001 | 1020 | 10 |
20090702 | 00002 | 1010 | 5 |
20090702 | 00003 | 3010 | 20 |
20090703 | 00001 | 1030 | 10 |
20090703 | 00002 | 1020 | 15 |
20090704 | 00001 | 2020 | 30 |
20090704 | 00002 | 3010 | 20 |
以下のコードは、売上データsalesを「五十音順でsales_noの昇順」にソートします。
usort( $sales, "comp" ); function comp( $sale1, $sale2 ) { // 引数1と引数2はそれぞれ売上データ。 // 売上データからsales_noを取得する。 $sales_no1 = $sale1["sales_no"]; $sales_no2 = $sale2["sales_no"]; //////////////////////////////////////////// // sales_noを比較する。 //////////////////////////////////////////// if ( $sales_no1 === $sales_no2 ) { // sales_noが一致する場合: 引数1と引数2は同列。 return 0; } if ( $sales_no1 > $sales_no2 ) { // 引数1のsales_noの方が大きい: 引数2→引数1の順に並べる return 1; } else { // 引数1のsales_noの方が小さい: 引数1→引数2の順に並べる return -1; } }
ソート後の売上データsalesをブラウザに表示すると、以下のようになります。
売上日 | 売上番号 | 商品ID | 数量 |
---|---|---|---|
20090704 | 00001 | 2020 | 30 |
20090702 | 00001 | 1020 | 10 |
20090703 | 00001 | 1030 | 10 |
20090704 | 00002 | 3010 | 20 |
20090702 | 00002 | 1010 | 5 |
20090703 | 00002 | 1020 | 15 |
20090702 | 00003 | 3010 | 20 |
ソートの例(数値順)
例をもう一つ挙げます。商品データproductsを特定の項目の「数値順」にソートします。
$products = array(); $products= array( product_id => "2010", product_name => "定規", price => 140 ); $products= array( product_id => "2020", product_name => "コンパス", price => 300 ); $products= array( product_id => "3010", product_name => "のり", price => 200 ); $products= array( product_id => "1030", product_name => "消しゴム", price => 100 ); $products= array( product_id => "1020", product_name => "ボールペン", price => 100 ); $products= array( product_id => "1010", product_name => "えんぴつ", price => 80 );
商品データproductsをブラウザに表示すると、以下のようになります。
商品ID | 商品名 | 価格 |
---|---|---|
2010 | 定規 | 140 |
2020 | コンパス | 300 |
3010 | のり | 200 |
1030 | 消しゴム | 100 |
1020 | ボールペン | 100 |
1010 | えんぴつ | 80 |
以下のコードは、商品データproductsを「数値順でproduct_idの降順」にソートします。
usort( $products, "comp" ); function comp( $product1, $product2 ) { // 引数1と引数2はそれぞれ商品データ。 // 商品データのproduct_idを取得する。 $product_id1 = $product1["product_id"]; $product_id2 = $product2["product_id"]; //////////////////////////////////////////// // product_idを比較する。 //////////////////////////////////////////// // 引き算によりproduct_idの大小を比較する。 // ・引数2のproduct_idの方が大きければ、戻り値は正の値: 引数2→引数1の順に並ぶ。 // ・product_idが一致すれば、戻り値は0: 引数1と引数2の同列。 // ・引数1のproduct_idの方が大きければ、戻り値は負の値: 引数1→引数2の順に並ぶ。 return $product_id2 - $product_id1; }
ソート後の商品データproductsをブラウザに表示すると、以下のようになります。
商品ID | 商品名 | 価格 |
---|---|---|
3010 | のり | 200 |
2020 | コンパス | 300 |
2010 | 定規 | 140 |
1030 | 消しゴム | 100 |
1020 | ボールペン | 100 |
1010 | えんぴつ | 80 |
■結合
2種類のデータを、特定の条件で結合するアルゴリズムです。
例として、商品データproductsと売上データsalesを結合します。
$products = array(); $products= array( product_id => "1010", product_name => "えんぴつ", price => 80 ); $products= array( product_id => "1020", product_name => "ボールペン", price => 100 ); $products= array( product_id => "1030", product_name => "消しゴム", price => 100 ); $products= array( product_id => "2010", product_name => "定規", price => 140 ); $products= array( product_id => "2020", product_name => "コンパス", price => 300 ); $products= array( product_id => "3010", product_name => "のり", price => 200 ); $sales = array(); $sales= array( sales_date => "20090702", sales_no => "00001", product_id => "1020", amount => 10 ); $sales= array( sales_date => "20090702", sales_no => "00002", product_id => "1010", amount => 5 ); $sales= array( sales_date => "20090702", sales_no => "00003", product_id => "3010", amount => 20 ); $sales= array( sales_date => "20090703", sales_no => "00001", product_id => "1030", amount => 10 ); $sales= array( sales_date => "20090703", sales_no => "00002", product_id => "1020", amount => 15 ); $sales= array( sales_date => "20090704", sales_no => "00001", product_id => "2020", amount => 30 ); $sales[]= array( sales_date => "20090704", sales_no => "00002", product_id => "3010", amount => 20 );
商品データproductsをブラウザに表示すると以下のようになります。
商品ID | 商品名 | 価格 |
---|---|---|
1010 | えんぴつ | 80 |
1020 | ボールペン | 100 |
1030 | 消しゴム | 100 |
2010 | 定規 | 140 |
2020 | コンパス | 300 |
3010 | のり | 200 |
売上日 | 売上番号 | 商品ID | 数量 |
---|---|---|---|
20090702 | 00001 | 1020 | 10 |
20090702 | 00002 | 1010 | 5 |
20090702 | 00003 | 3010 | 20 |
20090703 | 00001 | 1030 | 10 |
20090703 | 00002 | 1020 | 15 |
20090704 | 00001 | 2020 | 30 |
20090704 | 00002 | 3010 | 20 |
以下のコードは、商品データと売上データをproduct_idをキーとして結合します。
///////////////////////////////////////////////////////////////////////////////// // ハッシュテーブルを作成し、 product_idをキーとして商品データを取得できるようにする。 ///////////////////////////////////////////////////////////////////////////////// // ハッシュテーブル $hash_table = array(); // すべての商品データについて繰り返す。 for ( $i = 0; $i < count( $products ); ++$i ) { $product = $products[$i]; // 商品データのproduct_idを取得する。 $key = $product["product_id"]; // product_idをキーとして、商品データをハッシュテーブルに格納する。 $hash_table[$key] = $product; } ///////////////////////////////////////////////////////////////////////////////// // 売上データと商品データを結合する。 ///////////////////////////////////////////////////////////////////////////////// // すべての売上データについて繰り返す。 for ( $i = 0; $i < count( $sales ); ++$i ) { $sale = $sales[$i]; // 売上データのproduct_idを取得する。 $product_id = $sale["product_id"]; // product_idをキーとして、商品データをハッシュテーブルから取得する。 $product = $hash_table[$product_id]; if ( $product !== undefined ) { // 商品データを取得できた場合: // 商品データの値を売上データに格納する。 $sale["product_name"] = $product["product_name"]; $sale["price"] = $product["price"]; $sales[$i] = $sale; } }
結合後の売上データsalsesをブラウザに表示すると、以下のようになります。
売上日 | 売上番号 | 商品ID | 商品名 | 数量 | 価格 |
---|---|---|---|---|---|
20090702 | 00001 | 1020 | ボールペン | 10 | 100 |
20090702 | 00002 | 1010 | えんぴつ | 5 | 80 |
20090702 | 00003 | 3010 | のり | 20 | 200 |
20090703 | 00001 | 1030 | 消しゴム | 10 | 100 |
20090703 | 00002 | 1020 | ボールペン | 15 | 100 |
20090704 | 00001 | 2020 | コンパス | 30 | 300 |
20090704 | 00002 | 3010 | のり | 20 | 200 |
■集計
複数のデータを特定の条件で集計するアルゴリズムです。
例として、売上データsalesを集計します。
$sales = array(); $sales= array( sales_date => "20090702", sales_no => "00001", product_name => "ボールペン", price => 100, amount => 10 ); $sales= array( sales_date => "20090702", sales_no => "00002", product_name => "えんぴつ", price => 80, amount => 5 ); $sales= array( sales_date => "20090702", sales_no => "00003", product_name => "のり", price => 200, amount => 20 ); $sales= array( sales_date => "20090703", sales_no => "00001", product_name => "消しゴム", price => 100, amount => 10 ); $sales= array( sales_date => "20090703", sales_no => "00002", product_name => "ボールペン", price => 100, amount => 15 ); $sales= array( sales_date => "20090704", sales_no => "00001", product_name => "コンパス", price => 300, amount => 30 ); $sales[]= array( sales_date => "20090704", sales_no => "00002", product_name => "のり", price => 200, amount => 20 );
売上データsalesをブラウザに表示すると以下のようになります。
売上日 | 売上番号 | 商品名 | 価格 | 数量 |
---|---|---|---|---|
20090702 | 00001 | ボールペン | 100 | 10 |
20090702 | 00002 | えんぴつ | 80 | 5 |
20090702 | 00003 | のり | 200 | 20 |
20090703 | 00001 | 消しゴム | 100 | 10 |
20090703 | 00002 | ボールペン | 100 | 15 |
20090704 | 00001 | コンパス | 300 | 30 |
20090704 | 00002 | のり | 200 | 20 |
以下のコードは、salesを集計してsales_date毎の合計数量と合計売上高を求めます。
/////////////////////////////////////////////////////// // 集計結果の初期化 /////////////////////////////////////////////////////// // 集計結果を一時的に格納するマップ配列 $resultsTmp = array(); // すべての売上データについて繰り返す。 for ( $i = 0; $i < count( $sales ); ++$i ) { $sale = $sales[$i]; // 売上データのsales_dateを取得する。 $sales_date = $sale["sales_date"]; if ( ! array_key_exists( $sales_date, $resultsTmp ) ) { // オブジェクトにキーsales_dateが含まれていない: // 集計結果の初期値を生成する。 $result = array( "sales_date" => $sales_date, "amount" => 0, "total" => 0 ); // 生成した初期値をキーsales_dateに関連付けてオブジェクトに格納する。 $resultsTmp[$sales_date] = $result; } } /////////////////////////////////////////////////////// // salesを集計 /////////////////////////////////////////////////////// // すべての売上データについて繰り返す。 for ( $i = 0; $i < count( $sales ); ++$i ) { $sale = $sales[$i]; // 売上データのsales_dateを取得する。 $sales_date = $sale["sales_date"]; // キーsales_dateに関連付く集計結果をオブジェクトから取得する。 $result = $resultsTmp[$sales_date]; // 売上データのamountを集計結果に足し合わせる。 $result["amount"] += $sale["amount"]; // 売上データのpriceとamountとを掛けた値を集計結果に足し合わせる。 $result["total"] += $sale["price"] * $sale["amount"]; $resultsTmp[$sales_date] = $result; } /////////////////////////////////////////////////////// // 集計結果を通常の配列に移し替え /////////////////////////////////////////////////////// $results = array(); // 一時オブジェクトの全てのデータについて繰り返す。 foreach ( $resultsTmp as $result ) { // データを配列に追加する $results[]= $result; }
集計結果は変数resultsに格納されます。集計結果resultsをブラウザに表示すると以下のようになります。
売上日 | 合計数量 | 合計売上高 |
---|---|---|
20090702 | 35 | 5400 |
20090703 | 25 | 2500 |
20090704 | 50 | 13000 |
データ構造
アルゴリズム
- Javaを使うなら理解しておきたいアルゴリズム - 抽出・ソート・結合・集計 (リスト&マップ編)
- Javaを使うなら理解しておきたいアルゴリズム - 抽出・ソート・結合・集計 (リスト&ビーン編)
- PHPを使うなら理解しておきたいアルゴリズム - 抽出・ソート・結合・集計
- VBAを使うなら理解しておきたいアルゴリズム - 抽出・結合・集計
- Javascriptを使うなら理解しておきたいアルゴリズム - 抽出・ソート・結合・集計
- SQLを使うなら理解しておきたいアルゴリズム?(というか、select文の書き方) - where・order by・join・group by
- Bashを使うなら理解しておきたいアルゴリズム - 抽出・ソート・結合・集計