PHPで質問です。次のarrayのリストを

$list= array(
0=>array('pid'=>'','name'=>'aaa'),
1=>array('pid'=>'0','name'=>'bbb'),
2=>array('pid'=>'3','name'=>'ccc'),
3=>array('pid'=>'4','name'=>'ddd'),
4=>array('pid'=>'1','name'=>'eee'),
5=>array('pid'=>'2','name'=>'fff'),
6=>array('pid'=>'1','name'=>'ggg'),
7=>array('pid'=>'','name'=>'hhh'),
);

次の用に出力してカテゴリーを作りたいのですが
再帰でやってみたのですがうまくいきませんでした。
出力:

aaa
∟bbb
| ∟eee
| | ∟ddd
| |   ∟ccc
| |     ∟fff
| ∟ggg
∟hhh

参考URLなどいらないので、
答えとなるソースを教えてください。
よろしくお願いします。

回答の条件
  • 1人2回まで
  • 登録:2007/01/29 11:58:52
  • 終了:2007/01/29 17:17:34

ベストアンサー

id:GEN111 No.1

GEN111回答回数472ベストアンサー獲得回数582007/01/29 15:28:04

ポイント36pt
<?php
$list = array(
  0=>array('pid'=>'','name'=>'aaa'),
  1=>array('pid'=>'0','name'=>'bbb'),
  2=>array('pid'=>'3','name'=>'ccc'),
  3=>array('pid'=>'4','name'=>'ddd'),
  4=>array('pid'=>'1','name'=>'eee'),
  5=>array('pid'=>'2','name'=>'fff'),
  6=>array('pid'=>'1','name'=>'ggg'),
  7=>array('pid'=>'','name'=>'hhh'),
  );

function show_categories($list) {
  foreach ($list as $key => $value) $list[$key] = array('id' => $key, 'pid' => ($value['pid'] == '' ? -1 : $value['pid']), 'name' => $value['name']) ;

  while ($list !== array()) {
    static $level = array('-1') ;
    static $branch = array() ;

    for(;;) {
      $cmp = '
if ($a["pid"] =='.end($level).' &amp;&amp; $b["pid"] != '.end($level).') return -1 ;
if ($b["pid"] =='.end($level).' &amp;&amp; $a["pid"] != '.end($level).') return 1 ;
if ($b["pid"] =='.end($level).' &amp;&amp; $a["pid"] == '.end($level).') ($a["name"] < $b["name"] ? -1 : 1) ;
if ($a["pid"] != $b["pid"]) return ((int)$a["pid"] > (int)$b["pid"] ? 1 : -1) ;
return ($a["name"] < $b["name"] ? -1 : 1) ;
' ;
      usort($list, create_function('$a, $b', $cmp)) ;
      $first = reset($list) ;
      if ($first['pid'] == end($level)) break ;
      array_pop($level) ;
      array_pop($branch) ;
    }

    $one = array_shift($list) ;
    echo implode($branch).($one['id'] !=  0 ? '∟' : '').$one['name']."\n" ;
    $next = reset($list) ;
    $branch[] = ($next['pid'] == end($level) ? '|' : ' ') ;
    $level[] = $one['id'] ;
  }
}

echo "<pre>" ;
show_categories($list) ;
echo "</pre>" ;
?>

もう少しすっきりできるかもしれませんが。

id:chibitomo

いちばんすっきりしました。

大変ありがとうございました!

2007/01/29 17:15:02

その他の回答(3件)

id:GEN111 No.1

GEN111回答回数472ベストアンサー獲得回数582007/01/29 15:28:04ここでベストアンサー

ポイント36pt
<?php
$list = array(
  0=>array('pid'=>'','name'=>'aaa'),
  1=>array('pid'=>'0','name'=>'bbb'),
  2=>array('pid'=>'3','name'=>'ccc'),
  3=>array('pid'=>'4','name'=>'ddd'),
  4=>array('pid'=>'1','name'=>'eee'),
  5=>array('pid'=>'2','name'=>'fff'),
  6=>array('pid'=>'1','name'=>'ggg'),
  7=>array('pid'=>'','name'=>'hhh'),
  );

function show_categories($list) {
  foreach ($list as $key => $value) $list[$key] = array('id' => $key, 'pid' => ($value['pid'] == '' ? -1 : $value['pid']), 'name' => $value['name']) ;

  while ($list !== array()) {
    static $level = array('-1') ;
    static $branch = array() ;

    for(;;) {
      $cmp = '
if ($a["pid"] =='.end($level).' &amp;&amp; $b["pid"] != '.end($level).') return -1 ;
if ($b["pid"] =='.end($level).' &amp;&amp; $a["pid"] != '.end($level).') return 1 ;
if ($b["pid"] =='.end($level).' &amp;&amp; $a["pid"] == '.end($level).') ($a["name"] < $b["name"] ? -1 : 1) ;
if ($a["pid"] != $b["pid"]) return ((int)$a["pid"] > (int)$b["pid"] ? 1 : -1) ;
return ($a["name"] < $b["name"] ? -1 : 1) ;
' ;
      usort($list, create_function('$a, $b', $cmp)) ;
      $first = reset($list) ;
      if ($first['pid'] == end($level)) break ;
      array_pop($level) ;
      array_pop($branch) ;
    }

    $one = array_shift($list) ;
    echo implode($branch).($one['id'] !=  0 ? '∟' : '').$one['name']."\n" ;
    $next = reset($list) ;
    $branch[] = ($next['pid'] == end($level) ? '|' : ' ') ;
    $level[] = $one['id'] ;
  }
}

echo "<pre>" ;
show_categories($list) ;
echo "</pre>" ;
?>

もう少しすっきりできるかもしれませんが。

id:chibitomo

いちばんすっきりしました。

大変ありがとうございました!

2007/01/29 17:15:02
id:worldtravel No.2

worldtravel回答回数34ベストアンサー獲得回数42007/01/29 14:32:50

これだけではできない気がするのですが...

私の勘違いでできたらすいません。

もちろんポイント不要です。


bbbとhhhはaaaの下にありますが、何を判断基準にしているのでしょうか。

また、eeeやgggはなぜhhhの下ではなくbbbの下に来るのでしょうか。

id:chibitomo

質問を質問でかえすなよ・・・。

2007/01/29 17:12:59
id:pacochi No.3

ぱこち回答回数247ベストアンサー獲得回数1132007/01/29 14:37:36

ポイント27pt
$list= array(
0=>array('pid'=>'','name'=>'aaa'),
1=>array('pid'=>'0','name'=>'bbb'),
2=>array('pid'=>'3','name'=>'ccc'),
3=>array('pid'=>'4','name'=>'ddd'),
4=>array('pid'=>'1','name'=>'eee'),
5=>array('pid'=>'2','name'=>'fff'),
6=>array('pid'=>'1','name'=>'ggg'),
7=>array('pid'=>'','name'=>'hhh'),
);

$list_copy = $list;
$list_tree = search_child();
$nest_count = array();
$l_flag = array();
$list_text = make_tree($list_tree, 0);

#print_r($list_tree);
exit($list_text);

function search_child($pid = -2) {

	global $list_copy;

	$list_tree = array();

	for ($i = 0; $i < count($list_copy); $i++) {

		if (isset($list_copy[$i]['get'])) continue;
		$i_pid = ($list_copy[$i]['pid'] === '') ? -1 : intval($list_copy[$i]['pid']);
		$i_name = $list_copy[$i]['name'];

		if ($i_pid == $pid + 1) {

			$list_copy[$i]['get'] = true;
			$list_tree[$i_name] = search_child($i_pid);

		}


	}

	return($list_tree);

}

function make_tree($list_tree, $nest) {

	global $nest_count, $l_flag;

	$list_text = '';
	if (isset($nest_count[$nest])) $nest_count[$nest] = 0;
	if (isset($l_flag[$nest])) $l_flag[$nest] = false;

	foreach ($list_tree as $name => $list_tree_c) {

		$nest_count[$nest]++;
		if ($nest_count[$nest] == count($list_tree)) $l_flag[$nest] = true;

		for ($i = 0; $i < $nest; $i++) {

			$list_text .= ($l_flag[$i]) ? ' ' : '┃';

		}

		$list_text .= "┗{$name}\n";

		if (count($list_tree_c)) $list_text .= make_tree($list_tree_c, $nest + 1);

	}

	return($list_text);

}

出力がちょっと違っていますがやりたい事はこんな事でしょうか。

id:chibitomo

こんな感じです。

ありがとうございました!

2007/01/29 17:14:00
id:takfjt No.4

takfjt回答回数23ベストアンサー獲得回数32007/01/29 15:03:36

ポイント27pt

例出力のhhhは間違っていると判断しました.

$list= array(

0=>array('pid'=>'','name'=>'aaa'),

1=>array('pid'=>'0','name'=>'bbb'),

2=>array('pid'=>'3','name'=>'ccc'),

3=>array('pid'=>'4','name'=>'ddd'),

4=>array('pid'=>'1','name'=>'eee'),

5=>array('pid'=>'2','name'=>'fff'),

6=>array('pid'=>'1','name'=>'ggg'),

7=>array('pid'=>'','name'=>'hhh'),

);

function show_tree($list, $pid, $bar)

{

$a = array();

for ($i = 0; $i < count($list); $i++) {

if ($list[$i]['pid'] == $pid) {

$list[$i]['id'] = $i;

array_push($a, $list[$i]);

}

}

array_push($bar, "| ");

for ($i = 0; $i < count($a); $i++) {

for ($j = 0; $j < count($bar) - 1; $j++) {

print "$bar[$j]";

}

if (count($bar) > 1) {

print "∟";

}

print $a[$i]['name'];

print "\n";

if ($i == count($a) - 1) {

array_pop($bar);

array_push($bar, " ");

}

$id = $a[$i]['id'];

show_tree($list, "$id", $bar);

}

}

show_tree($list, '', array());

id:chibitomo

明快です。ありがとうございました!

2007/01/29 17:14:37
  • id:worldtravel
    失礼しました。
    私の勘違いでした。
  • id:GEN111
    function show_categories2($list) {
    foreach ($list as $key => $value) $list[$key] =
    array('id' => $key,
    'pid' => ($value['pid'] == '' ? -1 : $value['pid']),
    'name' => $value['name']) ;

    while ($list !== array()) {
    static $level = array(-1) ;
    static $branch = array() ;

    for(;;) {
    $cmp = '
    if ($a["pid"] =='.end($level).' && $b["pid"] != '.end($level).') return -1 ;
    if ($b["pid"] =='.end($level).' && $a["pid"] != '.end($level).') return 1 ;
    if ($a["pid"] != $b["pid"]) return ((int)$a["pid"] > (int)$b["pid"] ? 1 : -1) ;
    return ($a["name"] < $b["name"] ? -1 : 1) ;' ;

    usort($list, create_function('$a, $b', $cmp)) ;
    if ($list[0]['pid'] == end($level)) break ;
    array_pop($level) ;
    array_pop($branch) ;
    }

    $one = array_shift($list) ;
    echo implode($branch).($one['id'] != 0 ? '∟' : '').$one['name']."\n" ;
    $branch[] = ($list[0]['pid'] == end($level) ? '|' : ' ') ;
    $level[] = $one['id'] ;
    }
    }
    不要な記述があったので修正。
    いるかを付けていただいて恐縮ですが、他の回答よりかなり遅いです。

この質問への反応(ブックマークコメント)

「あの人に答えてほしい」「この質問はあの人が答えられそう」というときに、回答リクエストを送ってみてましょう。

これ以上回答リクエストを送信することはできません。制限について

絞り込み :
はてなココの「ともだち」を表示します。
回答リクエストを送信したユーザーはいません