コード:
// Mmmm... functiony goodness
function array_to_toc ($in, &$out, $level = '') {
if (!$level) $out = array(); // Make sure $out is an empty array at the beginning
foreach ($in as $key => $item) { // Loop items
$thisLevel = ($level) ? "$level.".($key + 1) : ($key + 1); // Get this level as string
$out[$thisLevel] = $item['name']; // Add this item to $out
if (isset($item['subs']) && is_array($item['subs']) && count($item['subs'])) array_to_toc($item['subs'],$out,$thisLevel); // Recurse children of this item
}
}
// Here is your test data (slightly modified - I think you stated it wrong in the question)
$array = array (
0 => array (
'name' => 'test1',
'subs' => array (
0 => array (
'name' => 'test2'
),
1 => array (
'name' => 'test3',
'subs' => array (
0 => array (
'name' => 'test4'
)
)
)
)
),
1 => array (
'name' => 'test5'
)
);
// $result is passed by reference and will hold the output after the function has run
$result = array();
array_to_toc($array, $result);
print_r($result);
出力:
Array
(
[1] => test1
[1.1] => test2
[1.2] => test3
[1.2.1] => test4
[2] => test5
)
Demo
EDIT
これら2つ(プラスワン支援)機能は、あなたからの章を追加および削除が可能aを入力章の参照によるrray。次に、新しい構造からTOCを再計算することができます。
function chapter_exists ($array, $chapterId) {
$chapterParts = explode('.',$chapterId);
foreach ($chapterParts as &$chapter) $chapter--;
$lastId = array_pop($chapterParts);
return eval('return isset($array['.implode("]['subs'][",$chapterParts).((count($chapterParts)) ? "]['subs'][" : '')."$lastId]);");
}
function add_chapter (&$array, $chapterId, $item) {
$chapterParts = explode('.',$chapterId);
foreach ($chapterParts as &$chapter) $chapter--; // Decrement all the values
$lastId = array_pop($chapterParts);
if (count($chapterParts) && !chapter_exists($array, implode('.',$chapterParts))) return FALSE; // Return FALSE if the level above the chapter we are adding doesn't exist
if (chapter_exists($array, $chapterId)) { // See if the chapter reference already exists
eval('array_splice($array'.((count($chapterParts)) ? '['.implode("]['subs'][",$chapterParts)."]['subs']" : '').",$lastId,0,array(\$item));"); // Insert an item
} else {
eval('$array['.implode("]['subs'][",$chapterParts).((count($chapterParts)) ? "]['subs'][" : '')."$lastId] = \$item;"); // Insert an item
}
return TRUE;
}
function remove_chapter (&$array, $chapterId) {
$chapterParts = explode('.',$chapterId);
foreach ($chapterParts as &$chapter) $chapter--; // Decrement all the values
$lastId = array_pop($chapterParts);
return (chapter_exists($array, $chapterId)) ? eval('$removed = array_splice($array'.((count($chapterParts)) ? '['.implode("]['subs'][",$chapterParts)."]['subs']" : '').",$lastId,1); return array_shift(\$removed);") : FALSE;
}
どのように動作するかを実証する最も良い方法は、例です。上の配列構造から始めて、$structure
という変数に格納されているとします。私たちが知っているように、私たちの結果のTOCの配列は次のようになります。
Array
(
[1] => test1
[1.1] => test2
[1.2] => test3
[1.2.1] => test4
[2] => test5
)
を今は、我々は章1.2
を削除するかを決定し、すべてはそれがサブ章だ - 私たちはこれを行うことができます:
// Remove the chapter from $structure
remove_chapter($structure, '1.2');
// recalculate the TOC
array_to_toc($structure, $result2);
print_r($result2);
/*
Outputs:
Array
(
[1] => test1
[1.1] => test2
[2] => test5
)
*/
今すぐことができます章1.1
としてtest6
と呼ばれ、test2
は1.2
に再インデックスされます、我々は章を追加したいと言う - 私たちは、この1のために、上記の例の結果で作業することがあります:
// Add the new chapter to $structure
add_chapter($structure, '1.1', array('name'=>'test6'));
// recalculate the TOC
array_to_toc($structure, $result3);
print_r($result3);
/*
Outputs:
Array
(
[1] => test1
[1.1] => test6
[1.2] => test2
[2] => test5
)
*/
OK、かなりシンプルなようです。しかし、我々がに移動したいのであれば、をサブチャプターに移動すると、それはツリーの最上位にありますか?のは、このことを実証する$structure
の私達の元のバージョンに戻りましょう - それは今章3
であるように、我々は、章1.2
を移動します:
/*
A quick reminder of what we are starting with:
Array
(
[1] => test1
[1.1] => test2
[1.2] => test3
[1.2.1] => test4
[2] => test5
)
*/
// Remove the chapter from $structure - this time, we'll catch the items we remove in a variable
$removed = remove_chapter($structure, '1.2');
// Add it again, only this time as chapter 3
add_chapter($structure, '3', $removed);
// recalculate the TOC
array_to_toc($structure, $result4);
print_r($result4);
/*
Outputs:
Array
(
[1] => test1
[1.1] => test2
[2] => test5
[3] => test3
[3.1] => test4
)
*/
がうまくいけば、私はそこにそれが十分に説明してきました。
chapter_exists()
はブール値を返します。感じるならば、それが意味するものについてかなり自明です。最初のパラメーターとして$structure
配列を渡し、2番目のパラメーターとしてチェックするチャプターIDを渡します。他の2つの内部で使用されているので、この関数は必須です。
add_chapter()
はブール値を返します。したがって、操作が成功したかどうかをテストできます。章の親が存在しない場合は失敗します。たとえば、1.2
が定義されていない場合に1.2.1
を追加しようとすると、機能しません。既に存在するチャプターを追加すると、そのレベルのすべてのチャプター番号が1つ上にシフトされます。
remove_chapter()
は、成功すると削除されたアイテム(つまり配列)またはブール値FALSE
を返します。存在しない章を削除しようとすると失敗します。
NB:これは、任意のレベルの深さに対応するために、eval()
を多用しなければなりませんでした。私はそれを使用することを嫌っていますが、私は他の方法を考えることができませんでした - 誰かがこれを読んでいる人は、代替的なアプローチについての明るいアイデアを持っていれば、私に教えてください...
再帰関数:) –
私はあなたの質問に顕著な違いを参照いけない:http://stackoverflow.com/questions/7854940/php-walk-through-multidimensional-array-while-preserving-keysを - 私は再び同じ可能な重複をお勧めします。 – Gordon