PHP - обхождане на дърво. Нещо патладясах. Help!
Автор |
|
phrozencrewВто, 29.04.08, 20:17 |
Здрасти хора, Отново задрах за помощ. Знаете, че не съм програмист, но много се кефя на това изкуство и ето новата ми главоблъсканица. Не мога да се оправя с обхождането на дървовидна структура от данни. Ще дам пример:
И ей това нещо се опитвам да го обходя, като за целта търся кореновия елемент. Всъщност кореновите (родителните) елементи ги определям чрез двумерно асоциативно масивче така: ""=>"Food", "Food"=>"Fruit", "Fruit"=>"Green", "Green"=>"Pear", "Fruit"=>"Red", "Red"=>"Cherry", "Fruit"=>"Yellow", "Yellow"=>"Banana", "Food"=>"Meat", "Meat"=>"Beef", "Meat"=>"Pork" * "" => "Food" -> ключ => стойност. Food-a е родител и за това няма ключ. И от цялото това се опитах да създам функция, която да го обходи, но ето точно тук задрах: <?php
$ar = array(
""=>"Food",
"Food"=>"Fruit",
"Fruit"=>"Green",
"Green"=>"Pear",
"Fruit"=>"Red",
"Red"=>"Cherry",
"Fruit"=>"Yellow",
"Yellow"=>"Banana",
"Food"=>"Meat",
"Meat"=>"Beef",
"Meat"=>"Pork"
);
function display($masiv,$rod) {
foreach ($masiv as $roditel=>$dete){
if($roditel == $rod){
echo $dete."n";
}
display($masiv, $dete);
}
}
display($ar, "Food");
?> |
Както се казва "Къде сбъркахме??!". Както се вижда кода е на php, но нямам нищо против да ми дадете решение на Perl, Python или JavaScript. Аз обичам простите неща и винаги се стремя да обяснявам простичко. Ще съм благодарен, ако някой успее да ми обясни как да направя това обхождане ама като на малоумен. Вероятно тежкия ден си е казал думата, но със сигурност не виждам къде се забива кода. | | anonymousВто, 29.04.08, 22:01 |
здравей phrozencrew, според мен рекурсията тук е вредна! разгледай следните 2ф-ии: function display($masiv,$rod) {
foreach ($masiv as $roditel=>$dete){
if($roditel == $rod){
echo($roditel." : ".$dete." \n");
return;
}
}
return;
}
function _display($masiv,$rod) {
while($roditel = each ($masiv)){
if($roditel[0] == $rod){
print_r($roditel);
return;
}
}
return;
}
display($ar,"Food");
_display($ar,"Food"); |
имаш стойности, които се повтарят, напр. "Meat"=>"Beef", "Meat"=>"Pork" && "Food"=>"Fruit", "Food"=>"Meat", както се вижда от ф-ята _display последната стойност от декларацията на масива е актуална; също се вижда, че ключа се съхранява като число и асоциативен /print_r()/, т.е. "Food"=>"Fruit", "Food"=>"Meat", е все едно: $array_var["Food"]="Fruit"; $array_var["Food"]="Meat";
Edit 1: май трябва тримерен масив или подрязване на дървото Edit 2: направи echo(count($ar)." \n"); ми дава 7елемента, а те са повече в декларацията! редактиран от anonymous на 29.04.08 22:05 редактиран от anonymous на 29.04.08 22:07 редактиран от anonymous на 29.04.08 22:20 | | phrozencrewВто, 29.04.08, 22:20 | RE: PHP - обхождане на дърво. Нещо патладясах. Help!
” здравей phrozencrew, според мен рекурсията тук е вредна! разгледай следните 2ф-ии: function display($masiv,$rod) {
foreach ($masiv as $roditel=>$dete){
if($roditel == $rod){
echo($roditel." : ".$dete." n");
return;
}
}
return;
}
function _display($masiv,$rod) {
while($roditel = each ($masiv)){
if($roditel[0] == $rod){
print_r($roditel);
return;
}
}
return;
}
display($ar,"Food");
_display($ar,"Food"); |
имаш стойности, които се повтарят, напр. "Meat"=>"Beef", "Meat"=>"Pork" && "Food"=>"Fruit", "Food"=>"Meat", както се вижда от ф-ята _display последната стойност от декларацията на масива е актуална; също се вижда, че ключа се съхранява като число и асоциативен /print_r()/, т.е. "Food"=>"Fruit", "Food"=>"Meat", е все едно: $array_var["Food"]="Fruit"; $array_var["Food"]="Meat";
Edit: май трябва тримерен масив или подрязване на дървото „
Циклех си и аз нещо за тримерен масив, но си помислих, че няма нужда. А print_r() със сигурност няма да покаже целта на упражнението. Всъщност намерих едно решение на задачата, но там се използва MySQL база данни: <?php
function display_children($parent, $level) {
$result = mysql_query('SELECT title FROM tree '.
'WHERE parent="'.$parent.'";');
while ($row = mysql_fetch_array($result)) {
echo str_repeat(' ',$level).$row['title']."n";
display_children($row['title'], $level+1);
}
}
display_children('',0);
?> |
Аз не искам да ползвам MySQL, а простичка текстова база данни и идеята ми е да разбера как да го преобразувам горния код в подобен със същата концепция но за масив. ПС: Благодаря за ценната идея с: while($roditel = each ($masiv)){ |
Много ми харесва! И преди съм срещал while в комбинация с each, но някак си сега му обърнах необходимото внимание. | | anonymousВто, 29.04.08, 22:28 |
погледни Edit 2 на горния ми пост, плс. echo(count($ar)." \n"); $result = mysql_query('SELECT title FROM tree WHERE parent="'.$parent.'";'); -> с 2-мерен масив е все едно parent ga e primary/unique key, m.e. винаги връща NULL||1. (цикъл няма да е нужен), трябва да влезем в третото измерение или gets om *.txt file./без масиви/ | | anonymousВто, 29.04.08, 22:28 |
Ха ха ха гледам пуля се и нищо не разбирам баси как могат да се научат тези неща... | | anonymousВто, 29.04.08, 22:55 |
example code: // имаме следния масив
<?php
$ar = array(
""=>"Food",
"Food"=>"Fruit",
"Meat"=>"Bla 1",
"Meat"=>"Bla 2",
"Meat"=>"Bla 3",
"Meat"=>"Bla 4"
);
echo(count($ar)." \n");
while($roditel = each ($ar)) print_r($roditel);
?> |
Output /b console/: php example.php 3 //това е броя, а "трябваше" да е 6 Array ( [1] => Food [value] => Food [0] => [key] => ) Array ( [1] => Fruit [value] => Fruit [0] => Food [key] => Food ) Array ( [1] => Bla 4 [value] => Bla 4 [0] => Meat [key] => Meat ) print_r() показва какво и как е подредено в чекмеджето
Edit: подобна декларация на масива е равна на: $ar = array(
""=>"Food",
"Food"=>"Fruit",
"Meat"=>"Bla 1"
);
$ar["Meat"]="Bla 2";
$ar["Meat"]="Bla 3";
$ar["Meat"]="Bla 4";
// следва обхождането.
|
редактиран от anonymous на 29.04.08 23:08 | | anonymousСря, 30.04.08, 09:02 |
както се вижда при print_r(), a u om самата декларация на масива, имаме KEY =>value, затова двумерния масив може да се сравни c sql: SELECT ... WHERE pole=unique KEY... не само рекурсията, но и цикъл на обхождане е ненужен: function __display($masiv,$rod) {
echo("ключ ".$rod." : стойност ".$masiv[$rod]." \n");
return;
} |
| | phrozencrewСря, 30.04.08, 09:30 |
Аз пък взех да дълбая на другаде - да обединя ключовете и стойностите за да имам едномерен масив, което няма да попречи за неуникалните елементи. Виж до къде стигнах: text.txt - базата данни =>Food
Food=>Fruit
Fruit=>Green
Green=>Pear
Fruit=>Red
Red=>Cherry
Fruit=>Yellow
Yellow=>Banana
Food=>Meat
Meat=>Beef
Meat=>Pork |
Файла с който обхождам елементите: <?php
$handle = @fopen("text.txt", "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$ar[] = rtrim($buffer);
}
fclose($handle);
}
function display($masiv) {
foreach($masiv as $line){
list($parent, $dete) = preg_split('/=>/',$line);
echo $parent;
}
}
display($ar);
?> |
Разбира се не е довършено но сега нямам време. Отново благодаря за добрите идеи! | | phrozencrewСря, 30.04.08, 17:02 |
ЕЕеее, намерих ключа за бараката: <?php
$handle = @fopen("text.txt", "r");
if ($handle) {
while (!feof($handle)) {
$buffer = fgets($handle, 4096);
$ar[] = rtrim($buffer);
}
fclose($handle);
}
function display($masiv, $rod, $level) {
foreach($masiv as $line){
list($parent, $dete) = preg_split('/=>/',$line);
if($parent == $rod){
echo str_repeat(" ",$level).$dete."n";
$level = $level." ";
display($masiv, $dete, $level+1);
}
}
}
display($ar, "", 0);
?> |
| | anonymousСря, 30.04.08, 17:07 | редактиран от anonymous на 30.04.08 17:19 | | Коментар |