download.bg
 Вход Списание  Новини  Програми  Статии  Форум  Чат   Абонамент  Топ95   Архив 

PHP - обхождане на дърво. Нещо патладясах. Help!

< 1 2 >

Автор
Съобщение
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
супер

нещата отиват към XPath май? -> ako работата c XML ти допадне, ще е добре да отвориш 1тема от рода на XPath: въпроси и отговори, че не съм много в час там.

Edit:
http://garr.dl.sourceforge.net/sourceforge/phpxpath/PhpXPath-3.5.zip
http://heanet.dl.sourceforge.net/sourceforge/phpxpath/PhpXPath-3.5-Tests.zip

редактиран от anonymous на 30.04.08 17:19

< 1 2 >

Коментар

за нас | за разработчици | за реклама | станете автори | in english  © 1998-2024   Experta Ltd.