アプリ版:「スタンプのみでお礼する」機能のリリースについて

以下、タブは全角半角4つに変換しています。
<?php

$arrWBS = array("1", "1.1", "1.1.1", "1.2",
"1.2.1","1.2.1.1","1.2.1.2","1.2.1.3","1.2.1.3.1","1.2.3", "1.3", "1.4", "1.
5","1.5.1");
$rootWBS = "1";

のような配列(配列はソートされています)と文字列があり、
それをもとに、
getWBSHtml($arrWBS,$rootWBS);関数なるものをつくり、

上の例($rootWBS = "1";)だと以下のようなHTMLをはき出したいと思っています。

<ul>
    <li>1.1
        <ul>
            <li>1.1.1</li>
        </ul>
    </li>
    <li>1.2
        <ul>
            <li>1.2.1
                <ul>
                    <li>1.2.1.1</li>
                    <li>1.2.1.2</li>
                    <li>1.2.1.3</li>
                    <ul>
                        <li>1.2.1.3.1</li>
                    </ul>

                </ul>
            </li>
            <li>1.2.3</li>
        </ul>
    <li>1.3</li>
    <li>1.4</li>
    <li>1.5
        <ul>
            <li>1.5.1</li>
        </ul>
    </li>
    </li>
</ul>

===========================

そして、
$rootWBS = "1.2";だとすると、

<ul>
    <li>1.2.1
        <ul>
            <li>1.2.1.1</li>
            <li>1.2.1.2</li>
            <li>1.2.1.3</li>
            <ul>
                <li>1.2.1.3.1</li>
            </ul>

        </ul>
    </li>
    <li>1.2.3</li>
</ul>

となるHTMLをはき出したくおもっています。
(できれば整形したかたちで)
===========================


途中まで後述のように書いたのですが、完成せず、
また、$arrWBSを必要以上に走査して無駄な気がします。

どのようにすればこういったHTMLをはき出せるのでしょうか?
よろしくお願いします。

getWBSHtml($arrWBS,$rootWBS);
function getWBSHtml($arrWBS,$rootWBS){
    foreach($arrWBS as $data){
        if (preg_match("/^$rootWBS\.[^.]+$/",$data) > 0) {

            print "<ul>\n";
            print "<li>";
            print $data;
            getWBSHtml($arrWBS,$data);
            print "</li>\n";
            print "</ul>\n";
        }

    }
}


?>

A 回答 (4件)

配列の各要素ごとに次のような連想配列を作成します。



Array
(
[1] => Array
(
[0] => 1.1
[1] => 1.2
[2] => 1.3
[3] => 1.4
[4] => 1.5
)

[1.1] => Array
(
[0] => 1.1.1
)

[1.1.1] => Array
(
)

[1.2] => Array
(
[0] => 1.2.1
[1] => 1.2.3
)

[1.2.1] => Array
(
[0] => 1.2.1.1
[1] => 1.2.1.2
[2] => 1.2.1.3
)

[1.2.1.1] => Array
(
)

[1.2.1.2] => Array
(
)

[1.2.1.3] => Array
(
[0] => 1.2.1.3.1
)

[1.2.1.3.1] => Array
(
)

[1.2.3] => Array
(
)

[1.3] => Array
(
)

[1.4] => Array
(
)

[1.5] => Array
(
[0] => 1.5.1
)

[1.5.1] => Array
(
)

)

この配列を再帰的に処理すればOKです。全体はこんな感じです。

<?php

$arrWBS = array("1", "1.1", "1.1.1", "1.2",
"1.2.1","1.2.1.1","1.2.1.2","1.2.1.3","1.2.1.3.1","1.2.3", "1.3", "1.4", "1.5","1.5.1");

$rootWBS = "1";

// 連想配列の作成
$wbs_tree = array();
foreach($arrWBS as $data) {
$wbs_tree[$data] = array();
if (preg_match("/^(.*)\.[^.]+$/", $data, $matches) > 0) {
if(array_key_exists($matches[1], $wbs_tree)) {
array_push($wbs_tree[$matches[1]], $data);
}
}
}

// HTMLタグの作成
function getWBSHtml($datas, $indent, $wbs_tree) {
print(str_repeat(' ', $indent) . "<ul>\n");
foreach($datas as $name) {
print(str_repeat(' ', $indent+2) . "<li>");
print($name);
if (count($wbs_tree[$name]) > 0) {
print("\n");
getWBSHtml($wbs_tree[$name], $indent+4, $wbs_tree);
print(str_repeat(' ', $indent+2) . "</li>\n");
}
else {
print("</li>\n");
}
}
print(str_repeat(' ', $indent) . "</ul>\n");
}

// 実行
getWBSHtml($wbs_tree[$rootWBS], 0, $wbs_tree);

?>
    • good
    • 0

<li>の終了タグは省略可なので、閉じなくても良いなら再帰処理すれば楽です。

ただしXHTMLだとアウト…。


function getWBSHtml($arrWBS,$rootWBS){
//必要な分だけ配列に
$arr = preg_grep("/^$rootWBS\.(\d+)/",$arrWBS);

echo "<ul>\n";
$ch = $flag = '';
foreach($arr as $val){
//更に下層があれば、重複判定flagつけて再帰。
if(preg_match("/^$rootWBS\.(\d+)\.(\d)/",$val,$arg)){
$ch = "$rootWBS.{$arg[1]}";
if($flag !== $ch){ $flag = $ch; getWBSHtml($arr,$ch);}
//それ以外なら出力
}else{
echo "<li>$val\n";
}
}
echo "</ul>\n";
return;
}
    • good
    • 0

前後関係だけを見て処理するならこんな感じ。


ただし相関関係があっているかは検証しないので微妙ですね

<?PHP
$arrWBS = array("1", "1.1", "1.1.1", "1.2","1.2.1","1.2.1.1","1.2.1.2","1.2.1.3","1.2.1.3.1","1.2.3", "1.3", "1.4", "1.5","1.5.1");
$space="\t";
foreach($arrWBS as $key=>$val){
$prev_num=$key==0?0:count(explode(".",$arrWBS[$key-1]));
$this_num=count(explode(".",$val));
$next_num=count($arrWBS)<=$key+1?0:count(explode(".",$arrWBS[$key+1]));
if($prev_num < $this_num){
$str.=str_repeat($space,$this_num -1);
$str.="<ul>\n";
}
$str.=str_repeat($space,$this_num);
$str.="<li>";
$str.=$val;
if($this_num == $next_num) $str.="</li>";
if($this_num >$next_num){
for($i=0;$i<$this_num -$next_num ;$i++){
if($i>0){
$str.="\n";
$str.=str_repeat($space,$this_num -$i);
}
$str.="</li>\n";
$str.=str_repeat($space,$this_num -1 -$i);
$str.="</ul>";
}
}
$str.="\n";
}
print "<pre>\n";
print htmlspecialchars($str);
print "</pre>\n";
print ($str);
?>
    • good
    • 0

値が数字だけだと抽象的すぎて何をしたいのか解り辛いけど…。



関数の記述はこの際置いておいて、配列を多次元の連想配列にした方が処理しやすい様な気がします。
で、変数の $rootWBS には、その時々に応じて必要な連想配列のキー名を代入して、関数側から呼び出して処理する様にすれば割とスマートな感じになるんじゃないのかなあと思います。
    • good
    • 0

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!