質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

Q&A

解決済

2回答

3448閲覧

多次元配列を入れ子のリストとして表示したい

riali

総合スコア7

多次元配列

1次元配列内にさらに配列を格納している配列を、多次元配列と呼びます。

PHP

PHPは、Webサイト構築に特化して開発されたプログラミング言語です。大きな特徴のひとつは、HTMLに直接プログラムを埋め込むことができるという点です。PHPを用いることで、HTMLを動的コンテンツとして出力できます。HTMLがそのままブラウザに表示されるのに対し、PHPプログラムはサーバ側で実行された結果がブラウザに表示されるため、PHPスクリプトは「サーバサイドスクリプト」と呼ばれています。

配列

配列は、各データの要素(値または変数)が連続的に並べられたデータ構造です。各配列は添え字(INDEX)で識別されています。

0グッド

1クリップ

投稿2018/05/22 06:31

編集2018/05/22 06:32

前提・実現したいこと

多次元配列を入れ子のリストとして表示したい
下記などのページも参照しましたが、未だ解決に至っていない状態です。
http://studio-key.com/1555.html
https://ja.stackoverflow.com/questions/7341/php%E5%A4%9A%E6%AC%A1%E5%85%83%E9%85%8D%E5%88%97%E3%81%8B%E3%82%89%E9%9A%8E%E5%B1%A4%E3%83%AA%E3%82%B9%E3%83%88%E3%82%BF%E3%82%B0ulli-liliulli-li-ul-li-ul%E3%82%92%E5%87%BA%E5%8A%9B%E3%81%97%E3%81%9F%E3%81%84

以下のような配列をPHPで以下のように入れ子のリストにしたいと考えています。

多次元配列

Array ( [0] => Array ( [id] => id1 [heading] => heading2 [text] => 見出し2 ) [1] => Array ( [id] => id2 [heading] => heading3 [text] => 見出し3 ) [2] => Array ( [id] => id3 [heading] => heading2 [text] => 見出し2 ) [3] => Array ( [id] => id4 [heading] => heading3 [text] => 見出し3 ) [4] => Array ( [id] => id5 [heading] => heading4 [text] => 見出し4 ) )

出力結果の例

<ul> <li> <a href="#id1">見出し2</a> <ul> <li><a href="#id2">見出し3</a></li> </ul> </li> <li> <a href="#id3">見出し2</a> <ul> <li> <a href="#id4">見出し3</a> <ul> <li><a href="#id5">見出し4</a></li> </ul> </li> </ul> </li> </ul>

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

システムが出す配列とのことで、お困りのようなので、試しにやってみました。phpは何でもできます。
(その配列を出すシステムは微妙です)

ある程度のパターンは考えましたが、うまくいかないこともあると思います。
手続的に順次処理しているので、コメントを参考に修正すれば、まあ対応できるのではないでしょうか。

php

1<?php 2$arr = 3[ 4 ["id" => "id1", "heading" => "heading2", "text" => "見出し2"], 5 ["id" => "id2", "heading" => "heading3", "text" => "見出し3"], 6 ["id" => "id3", "heading" => "heading2", "text" => "見出し2"], 7 ["id" => "id4", "heading" => "heading3", "text" => "見出し3"], 8 ["id" => "id5", "heading" => "heading4", "text" => "見出し4"], 9]; //質問の配列 10 11echo buildUL($arr, 0); //出力 12 13//アンカタグを作る 14function buildA($id, $text) { 15 return '<a href="#'.$id.'">'.$text.'</a>'; 16} 17 18//liタグを作る 19function buildLIs($array, $depth = 0) { //連想配列の配列と、インデントの深さをもらう 20 if(count($array) === 1) { return buildLI($array[0], $depth);} 21 $open = '<li>'; 22 $close = '</li>'; 23 $indent = ' '; 24 $ret = ''; 25 while(($cur = array_shift($array)) !== null) { //要素が尽きるまで、同一階層のli要素のループ 26 //配列の先頭を描画して 27 $ret .= str_repeat($indent, $depth).$open.PHP_EOL; 28 $ret .= str_repeat($indent, $depth + 1).buildA($cur["id"], $cur["text"]).PHP_EOL; 29 if(hasChild($cur, $array)) { //子階層を持っていたら、ループ中の配列から子供を飛ばして、子供の描画を移譲。 30 $children = pickChildren($cur, $array); 31 $array = array_slice($array, count($children)); 32 $ret .= buildUL($children, $depth + 1); 33 } 34 //配列の先頭に対応する閉じタグ 35 $ret .= str_repeat($indent, $depth).$close.PHP_EOL; 36 } 37 return $ret; 38} 39 40//li要素が一個しかないときの整形のため 41function buildLI($item, $depth = 0) { //連想配列を受ける(配列の配列ではなくて) 42 $open = '<li>'; 43 $close = '</li>'; 44 $indent = ' '; 45 46 $ret = str_repeat($indent, $depth).$open; 47 $ret .= buildA($item["id"], $item["text"]); 48 $ret .= $close.PHP_EOL; 49 return $ret; 50} 51 52//ulタグを作る 53function buildUL($array, $depth = 0) { 54 $open = '<ul>'; 55 $close = '</ul>'; 56 $indent = ' '; 57 58 $ret = str_repeat($indent, $depth).$open.PHP_EOL; 59 $ret .= buildLIs($array, $depth + 1); 60 $ret .= str_repeat($indent, $depth).$close.PHP_EOL; 61 return $ret; 62} 63 64//$arrayの中に、$parentの子となるものが存在するか。 65function hasChild($parent, $array) {//$parentは連想配列、$arrayは連想配列の配列 66 return $parent["heading"] < $array[0]["heading"]; 67} 68 69//$arrayの中の、$parentの子を取り出す。 70function pickChildren($parent, $array) {//$parentは連想配列、$arrayは連想配列の配列 71 $ret = []; 72 foreach($array as $item) { 73 if($parent["heading"] >= $item["heading"]) { //headingが自身と同じ以上だったら子でない 74 break; 75 } 76 $ret[] = $item; 77 } 78 return $ret; 79}

投稿2018/05/24 02:18

papinianus

総合スコア12705

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

ベストアンサー

配列の各要素が親子関係を定義していないのでいまのままでは無理ですね

投稿2018/05/22 06:34

yambejp

総合スコア114829

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

riali

2018/05/22 06:40

あまりPHPが多く理解ができておらず申し訳ないのですが http://studio-key.com/1555.html こちらの記事のように、 heading2の場合には1階層目、heading3の場合には2階層目、heading4の場合には3階層目という風にして、親子関係の配列に一度置き換えればいけるのかなと思っていたのですが、難しいのでしょうか?
KazuhiroHatano

2018/05/22 10:06

できなくはないけどそのやり方は最適じゃない 順番に依存して親子関係が決定するというのは 要素の追加とかソートとかがメンドくさくなってデータとしていじりにくい 元記事の通りparentにidを指定してやるようなやり方のほうが データとしてはいじりやすい 親子関係とか関係なく単にインデントの指定を ulの階層として解釈して出力したいということなら headingのところは整数値にしといたほうがやりやすかろう 名前もindentとかdepthとかの方が相応しいか 処理の概要としては現在のインデントレベルの変数を作って データをforeachで回して、指定のインデントが 現在のインデントと違えばulを閉じたり開始したりして 最後はインデント0までulを閉じるみたいな感じ
riali

2018/05/23 00:05

KazuhiroHatanoさま yambejpさま ご回答ありがとうございます。システムが出している配列なので追加などは難しそうなので一旦諦めることとしました。ありがとうございました。
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問