[英]Build an array tree from flat array and structured ID
如果您對問題感到困惑,請稍等一下,因為我不確定這是否完全正確。
SELECT * FROM `rules` ORDER BY `Rank_1` , `Rank_2` , `Rank_3` , `Rank_4` ASC
產量:
復制面食:
0 0 0 0 0
1 0 0 0 1
1 1 0 0 1.1
1 1 1 0 1.1.1
2 0 0 0 2
4 0 0 0 4
4 1 0 0 4.1
4 1 1 0 4.1.1
4 1 1 9 4.1.1.9
4 1 1 10 4.1.1.10
4 1 1 11 4.1.1.11
但是,此數據並不是我需要的形式,以便對其進行有用的處理。
我想遍歷所有規則,並根據自己的“深度”做不同的事情。 例如,我想使用RuleID = 0並執行<h1>
,1.1具有<h2>
但是當涉及到4.1.x時,打開一個<ul>
並給每個規則一個<li>
。
為此,我認為最好的方法是像選擇數組那樣選擇數據,最終得到的結果是:
array( 4 =>
array( 4.1 =>
array( 4.1.1 => 'rule content')
)
);
然后,我可以意識到我的深度並打開<ul>
標簽,循環遍歷該深度的規則,以此類推。
真正解決這個問題的最佳方法是什么? 我已經有很長一段時間了,老實說,不知道從這里去哪里。 我真的希望數據在同一張表中。 我想如果它們都在不同的表中,我可能可以解決此問題,但我不知道這肯定會更容易。
我從這條路線開始:
foreach($m as $rule) {
$depth = count(explode('.', $rule['ruleid']));
switch($depth) {
case 1:
echo '<h1>'.$rule['content'].'</h1>';
break;
case 2:
echo '<h2>'.$rule['content'].'</h2>';
break;
case 3:
echo '<strong>'.$rule['content'].'</strong>';
break;
}
echo '<br />\n';
}
然后我意識到這只是要單獨處理每個規則條目,而我的解決方案需要某種“意識”到規則中的位置,因此它可以知道何時打開標簽(例如<ul>
)然后在回顯規則中可能存在的列表項后再次關閉它(例如"Don't do: <ul><li>this</li><li>or this</li></ul>"
)
這是上面數據表中所需輸出的示例:
0.簡介
...
4.聊天
4.1。 做和不做
4.1.1。 做:
- 4.1.1.9要有禮貌
- 4.1.1.10要有耐心
- 4.1.1.11要聰明
希望一些火花能幫助到您!
假設從您的輸入數據中,您可以產生一個像這樣的數組:
$data = array(
'0' => 'content 0',
'1' => 'content 1',
'1.1' => 'content 1.1',
'1.1.1' => 'content 1.1.1',
'2' => 'content 2',
'4' => 'content 4',
'4.1' => 'content 4.1',
'4.1.1' => 'content 4.1.1',
'4.1.1.9' => 'content 4.1.1.9',
'4.1.1.10' => 'content 4.1.1.10',
'4.1.1.11' => 'content 4.1.1.11',
);
然后您可以將其轉換為樹狀結構:
// this will be our root node
// it has no content, but a place for children
$struct = array(
'children' => array()
);
foreach ($data as $ruleID => $content) {
// /\
// ||
// for every rule id in the input data we start at
// the root
// ||
// \/
$parent =& $struct;
// we split $ruleID at the dot to get a path, which we traverse
// ||
// \/
foreach (explode('.', $ruleID) as $val) {
// for every entry in the path we
// check if it's available in the current parent
// ||
// \/
if (!isset($parent['children'][$val])) {
// if not, we create an empty entry
$parent['children'][$val] = array(
'content' => '', // no content
'children' => array() // no children
);
}
// /\
// ||
// and then use either the new, or allready existent parent
// as the new parent
// ||
// || mind the assignment by reference! this
// \/ is the most important part
$parent =& $parent['children'][$val];
}
// after the whole path is traversed, we can
// finally add our content
// ||
// \/
$parent['content'] = $content;
}
print_r($struct);
演示: http : //codepad.org/vtMPjGoa
如果想以某種可能破壞各種樣式規則的方式將HTML與SQL混合,則可以添加“ ruledepth”列,然后在其上使用“ CASE”,例如:
SELECT othercols,
CASE
WHEN ruledepth=0 THEN CONCAT('<h1>', ruleid, '</h1>')
WHEN ruledepth=1 THEN CONCAT('<h2>', ruleid, '</h2>')
WHEN ruledepth=2 THEN CONCAT('<li>', rileid, '</li>')
etc
END FROM XXX WHERE .... ORDER BY ruleid........
對OPs代碼稍作修改。
您可以將$rule['ruleid']
到echo語句中,使其與所需的輸出完全相同。
$hasList=false;
foreach($m as $rule) {
$depth = count(explode('.', $rule['ruleid']));
// end previous list before starting with new rules
if ($hasList && $depth<4) {
echo '</ul>';
$hasList=false;
}
switch($depth) {
case 1:
echo '<h1>'.$rule['content'].'</h1>';
break;
case 2:
echo '<h2>'.$rule['content'].'</h2>';
break;
case 3:
echo '<strong>'.$rule['content'].'</strong>';
break;
case 4:
// start list if not already started
if (!$hasList) {
echo '<ul>';
$hasList=true;
}
echo '<li>'.$rule['content'].'</li>';
break;
}
//echo "<br />\n";
}
// end last list
if ($hasList) {
echo '</ul>';
$hasList=false;
}
我不確定這是否正是您所需要的,但是也許它將給您一些想法。
首先,您可以通過執行以下操作來確定規則的“深度”:
$depth = count(explode('.',$rule_id));
這將在上拆分您的規則ID .
並制作一個數組。 然后,它計算數組中的項目以確定深度。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.