Skip to content

Instantly share code, notes, and snippets.

@lighty
Last active August 29, 2015 13:57
Show Gist options
  • Save lighty/9366857 to your computer and use it in GitHub Desktop.
Save lighty/9366857 to your computer and use it in GitHub Desktop.
PHPでRDBから取得した配列データをコントロールブレイクでまとめたいなーと思って作って日の目を見なかったfunctionをIteratorとして統合
//********************************
// 配列のグループ化処理
//
// 指定したキーで、配列を以下の例の様にグルーピング
//
// $a = array(
// array("idA"=>1, "idB"=>"aaa", "val"=>"hoge1"),
// array("idA"=>1, "idB"=>"aaa", "val"=>"hoge2"),
// array("idA"=>1, "idB"=>"iii", "val"=>"fuga1"),
// array("idA"=>1, "idB"=>"iii", "val"=>"fuga2"),
// array("idA"=>2, "idB"=>"aaa", "val"=>"unko"),
// );
//
// $itr = new MultipleKeyIterator($a, array("idA", "idB"));
// foreach($itr as $key => $val){
// print "key:$key val:".print_r($val,true);
// }
//
// // 出力結果
//
// key:idA:1_idB:aaa val:Array
// (
// [0] => Array
// (
// [idA] => 1
// [idB] => aaa
// [val] => hoge1
// )
//
// [1] => Array
// (
// [idA] => 1
// [idB] => aaa
// [val] => hoge2
// )
//
// )
// key:idA:1_idB:iii val:Array
// (
// [0] => Array
// (
// [idA] => 1
// [idB] => iii
// [val] => fuga1
// )
//
// [1] => Array
// (
// [idA] => 1
// [idB] => iii
// [val] => fuga2
// )
//
// )
// key:idA:2_idB:aaa val:Array
// (
// [0] => Array
// (
// [idA] => 2
// [idB] => aaa
// [val] => unko
// )
//
// )
//
///********************************
class MultipleKeyIterator implements Iterator{
private $records = array();
private $multipleKeyValues = array();
public function __construct($records, $multipleKeys){
if (is_array($records)) {
$this->changeStructure($records,$multipleKeys);
}
}
public function rewind(){
reset($this->records);
reset($this->multipleKeyValues);
}
public function current() {
$multipleKey = current($this->multipleKeyValues);
$tmpArray = $this->records;
foreach($multipleKey as $key => $val){
$tmpArray = $tmpArray[$val];
}
return $tmpArray;
}
public function key(){
$multipleKey = current($this->multipleKeyValues);
$keyStr = array();
foreach($multipleKey as $key => $val){
$keyStr[] = "{$key}:{$val}";;
}
return implode("_", $keyStr);
}
public function next(){
return next($this->multipleKeyValues);
}
public function valid(){
$key = current($this->multipleKeyValues);
$records = ($key !== NULL && $key !== FALSE);
return $records;
}
private function changeStructure($records, $multipleKeys){
$newStructureRecords = array();
$workArray = array();
$multipleKeyValues = array();
foreach($records as $record){
foreach($multipleKeys as $key){
// ブレイクキーとなるカラムの値をworkArrayに保持している
$workArray[$key] = $record[$key];
}
$multipleKeyValues[] = $workArray;
// レコードを登録する処理
$tmpArray = &$newStructureRecords;
foreach($workArray as $key => $value){
$tmpArray = &$tmpArray[$value];
}
$tmpArray[] = $record;
}
$this->records = $newStructureRecords;
$this->multipleKeyValues = array_unique($multipleKeyValues, SORT_REGULAR);
}
}
@lighty
Copy link
Author

lighty commented Mar 5, 2014

こんなにがんばらなくても、keyの配列を文字列としてつなげる、という妥協をするだけでコードがすっきりした

function grouping($records, $keys){                                                                                                                                                              
    $groupingRecords = array();
    foreach($records as $record){
        $primaryKeyString = getPrimaryKeyString($keys, $record);
        $groupingRecords[$primaryKeyString][] = $record;
    }   
    return $groupingRecords;
}

function getPrimaryKeyString($keys, $record){
    $str = array();
    foreach($keys as $key){
        $str[] = "{$key}:{$record[$key]}";
    }   
    return implode("_", $str);
}

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment