こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

2次元配列を多次元配列にする。

2次元配列を多次元配列にする。

PHP5で
2次元目はすべて同じキーの2次元配列を
2次元目のキーごとの内容を共通項にまとめて、
多次元配列にする方法を教えてください。

キーの数は膨大なので、関数の再帰呼び出し
で、きれいに処理したいのです。

説明文では説明しきれないので、
やりたいことは↓の通りです。


array[0] = array([one] => "あ", [twe] => "う" [three] => "き");
array[1] = array([one] => "あ", [twe] => "う" [three] => "く");
array[2] = array([one] => "あ", [twe] => "え" [three] => "け");
array[3] = array([one] => "あ", [twe] => "え" [three] => "こ");
array[4] = array([one] => "い", [twe] => "お" [three] => "さ");
array[5] = array([one] => "い", [twe] => "お" [three] => "し");
array[6] = array([one] => "い", [twe] => "か" [three] => "す");
array[7] = array([one] => "い", [twe] => "か" [three] => "せ");

という配列があったら、これを↓のようにしたいです。

array(
[あ] => array(
[う] => array ("き", "く")
[え] => array ("け", "こ")
)
[い] => array(
[お] => array ("さ", "し")
[か] => array ("す", "せ")
)
  )

どうぞよろしくお願いいたします。

投稿日時 - 2010-04-30 11:48:08

QNo.5861563

すぐに回答ほしいです

質問者が選んだベストアンサー

関数の再帰呼び出しでは有りませんが、以下程度の処理では如何でしょう
<?php
$a = array(
array("one" => "あ", "two" => "う", "three" => "き")
,array("one" => "あ", "two" => "う", "three" => "く")
,array("one" => "あ", "two" => "え", "three" => "け")
,array("one" => "あ", "two" => "え", "three" => "こ")
,array("one" => "い", "two" => "お", "three" => "さ")
,array("one" => "い", "two" => "お", "three" => "し")
,array("one" => "い", "two" => "か", "three" => "す")
,array("one" => "い", "two" => "か", "three" => "せ")
);

$result=array();
foreach($array as $t){
$x=array();
$x[]=array_pop($t);
while(count($t)>0){
$x[array_pop($t)]=$x;
array_shift($x);
}
$result = array_merge_recursive($result,$x);
}

print_r($result);
?>

投稿日時 - 2010-05-02 19:29:22

お礼

どうも、ありがとうございます。
とても美しいコードですね。
参考にさせていただきました。

投稿日時 - 2010-05-10 10:45:14

ANo.4

このQ&Aは役に立ちましたか?

11人が「このQ&Aが役に立った」と投票しています

回答(5)

ANo.5

二次元配列であらわされたデータをツリー構造にするという課題という理解でよろしいのでしょうか。
「何次元になるか分からない」ということですが、ことなる要素数の配列がある場合にも
適用できるコードを考えてみました。ただし、ご要望のものとは少々ちがって、各配列の最後のデータも
キーとして扱うものです。

<?php
$arr = array
(
array('one'=>'あ', 'two'=>'か', 'three'=>'さ', 'four'=>'た', 'five'=>'な'),
array('one'=>'あ', 'two'=>'か', 'three'=>'さ', 'four'=>'た', 'five'=>'に'),
array('one'=>'あ', 'two'=>'か', 'three'=>'し', 'four'=>'た'),
array('one'=>'あ', 'two'=>'か', 'three'=>'し', 'four'=>'ち'),
array('one'=>'あ', 'two'=>'か', 'three'=>'す', 'four'=>'た'),
array('one'=>'あ', 'two'=>'き', 'three'=>'さ'),
array('one'=>'い', 'two'=>'か', 'three'=>'さ', 'four'=>'た'),
);

$data = array();

foreach($arr as $row)
{
$tmp =& $data; //参照渡しを使う
foreach($row as $item)
{
if(!isset($tmp[$item]))
$tmp[$item] = null;
$tmp =& $tmp[$item]; //参照渡しを使う
}
unset($tmp);
}

var_dump($data);

出力結果は次のようになります。
array(2) {
  ["あ"]=>
  array(2) {
    ["か"]=>
    array(3) {
      ["さ"]=>
      array(1) {
        ["た"]=>
        array(2) {
          ["な"]=>
          NULL
          ["に"]=>
          NULL
        }
      }
      ["し"]=>
      array(2) {
        ["た"]=>
        NULL
        ["ち"]=>
        NULL
      }
      ["す"]=>
      array(1) {
        ["た"]=>
        NULL
      }
    }
    ["き"]=>
    array(1) {
      ["さ"]=>
      NULL
    }
  }
  ["い"]=>
  array(1) {
    ["か"]=>
    array(1) {
      ["さ"]=>
      array(1) {
        ["た"]=>
        NULL
      }
    }
  }

投稿日時 - 2010-05-05 19:28:32

ANo.3

あまり綺麗でない気もしますが、下記のような形でも実装できました。
関数に渡される内部の配列は要素数が全て同一であるという前提です。

$a = array(
    array("one" => "あ", "two" => "う", "three" => "き")
    ,array("one" => "あ", "two" => "う", "three" => "く")
    ,array("one" => "あ", "two" => "え", "three" => "け")
    ,array("one" => "あ", "two" => "え", "three" => "こ")
    ,array("one" => "い", "two" => "お", "three" => "さ")
    ,array("one" => "い", "two" => "お", "three" => "し")
    ,array("one" => "い", "two" => "か", "three" => "す")
    ,array("one" => "い", "two" => "か", "three" => "せ")
  );

$rtn = func($a);
print_r($rtn);

function func($a) {
  $tmp = array();
  $out = array();

  foreach ($a as $arr) {
    $put = array_shift($arr);
    if (count($arr) === 0) {
      if (!in_array($put, $out)) {
        $out[] = $put;
      }
    } else {
      $tmp[$put][] = $arr;
    }
  }

  if (count($out) === 0) {
    foreach ($tmp as $key => $value) {
      $out[$key] = func($value);
    }
  }

  return $out;
}
(※インデントのために全角スペースを使っています)

投稿日時 - 2010-05-01 18:14:33

===================Q5861563-1.php050302==================
<?php
function main(){
/* 辞書順にソートされているものとする */
/* 連想配列の時もそんなに難しくはないとは思うけど、面倒なので省略 */
/*
Unicodeのコードポイント順で比較したいんですが、strcmpってそういう挙動します?
1バイトずつ並び替えてたらどうしよう。うまいサンプル知らないんだよね…。
*/
$a=array(
array("あ", "う", "き")
,array("あ", "う", "く")
,array("あ", "え", "け")
,array("あ", "え", "こ")
,array("い", "お", "さ")
,array("い", "お", "し")
,array("い", "か", "す")
,array("い", "か", "せ")
);

header("Content-Type:text/plain");
print_r(rec($a,0));

}

function rec($x,$p){
if(count($x,COUNT_NORMAL) === 1){
return $x;
}
while(count($x,COUNT_NORMAL) > 0){
$s = $x[0][0];
$y = array();
while(count($x,COUNT_NORMAL) !== 0){
if(strcmp($x[0][0],$s) !== 0 ){
break;
}
array_splice($x[0],0,1,NULL);
$y[] = $x[0];
array_splice($x,0,1,NULL);

}

$retval[$s] = rec($y,$p+1);
}
return $retval;

}

main();
?>
=====
出力結果
(見づらければユーザースタイルシート当てるなり、
教えてgooやOKWaveの回答のソースを見て判断して。
全角空白とかで代用するの嫌いなんで)

============
Array
(
[あ] => Array
(
[う] => Array
(
[き] => Array
(
[0] => Array
(
)

)

[く] => Array
(
[0] => Array
(
)

)

)

[え] => Array
(
[け] => Array
(
[0] => Array
(
)

)

[こ] => Array
(
[0] => Array
(
)

)

)

)

[い] => Array
(
[お] => Array
(
[さ] => Array
(
[0] => Array
(
)

)

[し] => Array
(
[0] => Array
(
)

)

)

[か] => Array
(
[す] => Array
(
[0] => Array
(
)

)

[せ] => Array
(
[0] => Array
(
)

)

)

)

)

投稿日時 - 2010-05-01 07:51:06

ANo.1

2次元配列ならさらっとforeachでやればいいような・・・

<?
$a=Array(
array("one" => "あ", "two" => "う", "three" => "き")
,array("one" => "あ", "two" => "う", "three" => "く")
,array("one" => "あ", "two" => "え", "three" => "け")
,array("one" => "あ", "two" => "え", "three" => "こ")
,array("one" => "い", "two" => "お", "three" => "さ")
,array("one" => "い", "two" => "お", "three" => "し")
,array("one" => "い", "two" => "か", "three" => "す")
,array("one" => "い", "two" => "か", "three" => "せ")
);

foreach($a as $data){
$b[$data["one"]][$data["two"]][]=$data["three"];
}
print "<pre>\n";
print_r( $b);
print "</pre>";

?>

投稿日時 - 2010-04-30 12:31:27

補足

説明不足で申し訳ないです。

3次元までなら上のやり方でもいいのですが、
何次元になるか分からない場合は、上の方法では無理です。

あと、同じキーの共通項目をまとめたいです。

投稿日時 - 2010-04-30 13:21:31

あなたにオススメの質問