Aiun Geschrieben 2. Februar 2008 Geschrieben 2. Februar 2008 hu, ich möchte ein bestimmtes Element eines Arrays manipulieren, allerdings wird das Array innerhalb eines Objekts verwaltet. Also class myCfgHandler { private $_cfg = array(); public function getCfg($path) { } public function setCfg($path,$value) { } }[/PHP] das cfg-Array ist mehrdimensional [PHP]array(' erstecfg => array(subcfg1 => 1, subcfg2 => array(subcfg1.1 => 'Hello World')) zweitecfg = array(cfg => 'hello World') ) nun möchte ich einzelne Konfigurationsbereiche abrufen können $cfghandler->getCfg('erstecfg.subcfg2.subcfg1.1'); oder etwas ähnliches. Das Array selbst soll das Objekt nie verlassen, da sich an dem Konfigurationformat noch zu viel ändern wird. jemand eine Idee wie ich aus einem String einen 'Pfad' in ein Array oder Objekt umwandeln kann, das ganze noch möglichst performant *g* ich will nicht unbedingt für jedes element $elem = $array foreach(split("\.",$path) as $sub) { $elem = $elem[$sub]; } [/PHP] das wären wohl viele verschwendete iterationen.... ideen ? danke Zitieren
flashpixx Geschrieben 2. Februar 2008 Geschrieben 2. Februar 2008 Hallo, um aus einem String ein Array zu machen, nimm "explode". Aber wenn Du Pfade ablegen willst, warum nimmst Du dann nicht einen Baum. Du kannst einen Baum als Array abspeichern und die Position der Blätter und Knoten entsprechend berechnen. HTH Phil Zitieren
Aiun Geschrieben 2. Februar 2008 Autor Geschrieben 2. Februar 2008 in der hoffnung dich richtig verstanden zu haben, genau darum geht es, das array ist ein Baum. nun kann es sein, das ich ein Element des Baumes von der Wurzel aus haben muss $baum->ast->unterast->unterunterast->unterunterunterast->blatt es kann aber auch sein, das ich bereits in einem Ast bin und von da aus weiter muss $unterunterast->unterunterunterast->blatt; der baum wird aber von einem einzelnen objekte verwaltet ergo immer $gärtner->gibAst($relative_position); ich hab es jetzt ersteinmal mit einem explode/split gemacht, hoffe aber noch auf einen performanteren weg. Zitieren
flashpixx Geschrieben 2. Februar 2008 Geschrieben 2. Februar 2008 Hallo, also zu dem Baum allgemein, der Pfad in einem Baum muss eindeutig sein. D.h. wenn Du relative Addressierung benötigst musst Du Dir irgendwie den aktuellen Knoten auf dem Du stehst merken. Das nächste ist was ist es für ein Baum, binär oder nicht. Wenn ich mich richtig erinnere dann kannst Du nur einen binären Baum als numerisches Array speichern. Aber was spricht dagegen, wenn Du einen Baum als Objekt erzeugst? Je nach Umfang würde ich den sogar in einer Datenbank hinterlegen, benötigst dafür ja nur eine Tabelle bzw wenn Du umfangreiche Daten hast zwei. Ich verstehe nicht so ganz die Problematik, denn so wie ich das sehe, ist das ein klassisches Lehrbuchbeispiel. Ich persönlich würde Dir empfehlen wirklich das ganze, da Du ja eh schon auf OOP Basis arbeitest, den Baum auch entsprechend so zu erstellen. Die Daten würde ich ebenfalls hierarchisch ablegen, so dass Du die Daten nur rekursiv einmal lesen musst. Ich nehme dafür meist direkt die Datenbank, weil man dann sehr schnell den Baum verändern kann. Ich nehme immer eine Tabelle mit 3 Feldern, Feld 1 (ID) ist PK mit Autoink, Feld 2 (ParentID, alle Knoten die unterhalb der Wurzelhängen, habe ParentID = 0) und ein Datenfeld je nach Bedarf. Das ganze durch eine Klasse sauber gekapselt und ich kann es für alles verwenden. Evtl. postest DU aber ein paar mehr Informationen, dann könnte man mal schauen, wie man es evtl verbessern kann HTH Phil Zitieren
Aiun Geschrieben 2. Februar 2008 Autor Geschrieben 2. Februar 2008 *g* ok,mehr Infos: ich arbeite seit einiger Zeit an einer Modul-basierten Anwendung, CMS-Modul, Forumsmodul, Galleriemodul etz. Nun will ich dem Administrator ermöglichen, einige dieser Module zu verbinden. Heißt, in einem Forum kann oberhalb der Beiträge oder Themenliste eine Seite aus dem CMS-Modul angezeigt werden. Oder, wenn es fertig ist, eine Abstimmung aus dem Poll-Modul. Dazu verwende ich ein Script, das der Administrator selbst eingibt. das kann so aussehen: Enviroment.Classname.objectwhatever.config.... zB. Sphere.Cms_Site_View.Template.file = usethistemplatenow.html Sphere.Cms_Site_View.Contentid = 3 Die Tiefe des Scripts ist nicht festgelegt. "Sphere" ist die Rootnode, "Cms_Site_View" ist der Klassenname bei dem das Script beginnt zu wirken. Nun würde innerhalb dieser Klasse Template ausgelesen und an das Objekt weitergegeben das dahinter steht. in der Klasse des Templates (Sphere_Template) käme dann nur noch file = ... an. Wenn jetzt aber Cms_Site_View diesen wert selbst benötigt, dann würde es heißen $script->getContext('Template.File'); das Script wird bereits in Objekte geparsed, ich dachte nur das Array beispiel würde eher antworten bringen Jeder Knoten wird in der Klasse Sphere_Tau_Context abgebildet. Subelemente können vom Typ String oder ebenfalls vom Typ Context sein. was in einem print_r in etwa so aussieht: Object Sphere_Tau_Context { [var1] = "Hello World" [var2] = Object Sphere_Tau_Context { [subvar1] = "myfile.html" } } [/PHP] Es geht also nicht um eine Datenbank o.ä. sondern um eine sehr flexible Konfigurationsmöglichkeit. Jeder Context-Knoten ist verwalter für sich und seine untergebenen Datenobjekte. Es kann also sein, das ein String gar kein String, sondern ein verweis auf eine Klasse / Methode ist, bei der ein Context diesen String abfragt. Mir geht es jetzt um die Performance. In dem Pfad zu navigieren, sagen wir, um 3 Ebenen abwärts, sind somit auch 3 iterationen nur um den Parameter aus ->getContext abzubilden. Ich kann aber auch nicht direkt über [PHP]$context->subcontext->subsubcontext gehen, da ja erst verarbeitet werden muss was in diesem Pfad angegeben ist. Zitieren
flashpixx Geschrieben 3. Februar 2008 Geschrieben 3. Februar 2008 Hallo, also ich bin mir nicht sicher ob ich Dich richtig verstehe. Ich habe nach dieser Auführung ein Objekt (Sphere) = Baum, die Knoten unterhalb von Sphere sind vom Type "Sphere_Tau_Context". Die Blätter sind vom Typ String. Was ich nun schon nicht verstehe, warum Du drei Typen verwendest? Denn der Baum besteht nur aus zwei Typen, Knoten und Blättern. Warum bleibst Du nicht bei dieser Definition? Wenn ich nun den Baum absteige kann ich doch prüfen, ob es sich um einen Knoten oder ein Blatt handelt, der Knoten ist ein komplexer Datentyp und die Blätter einfache, falls die Blätter auch komplexe Datentypen sind, dann kannst Du Dir von dem Objekt den Klassennamen geben lassen und auf diesen prüfen. Genauso wie Du Dir von jedem Objekt alle Eigenschaften geben lassen kannst. Wenn Du nun relativ navigieren willst dann muss Du die Baumstruktur entsprechend anpassen, denn normalerweise kannst Du nicht aufsteigen, sondern nur absteigen, d.h. Du benötigst innerhalb eines Knotens einen Zeiger auf den Vater. Im Groben würde mein Blatt / Knoten als Klasse so aussehen class Node { var $parent = null; var $subnodes = array(); var $data = null; var $nodename = null; var $nextlevelnode = null; } [/PHP] Wenn der Parent == null ist, ist es die Wurzel. Innerhalb der Subnodes werden alle weiteren Äste gespeichert, in Data werden die Daten des Knotens gespeichert und in Nodename der Namen des Knotens. Wichtig hierbei, Du musst dafür Sorge tragen dass alle Knoten auf einem Level im Baum eindeutige Namen haben. Dies kannst Du erreichen, in dem Du alle Knoten innerhalb einer Ebene in eine Liste / Array packst und bevor Du einen neuen Knoten einfügst dort prüft ob der Name vergeben ist (würde ich so realisieren, dass ich in jeder Node die nachfolgende auf gleicher ebene speichere also in Nextlevelnode). Im Prinzip kannst Du dann die Nodenamen zur Addressierung innerhalb Deines Baums verwenden. Zu der Frage mit der Performance, ich würde sagen, das kommt auf Komplexität des Baumes an. Meine Frage ist hierzu, warum speicherst Du eine Konfiguration als Baum und nicht einfach als flache Datenstruktur. Du kannst, bei Binärbäumen wird es öfters so gemacht, diese vollständig in ein Array ablegen. Kann man sicherlich hier auch machen, aber das Problem ist, man speichert immer von der Wurzel ausgehend die Kinder, d.h. wenn Du aufsteigen willst, dann musst Du immer von Beginn traversieren. In C würde man ja hier die einzelnen Knoten auf den Heap legen und die Speicheradresse aus dem Namen berechnen. Es gilt aber immer zuerst einmal den klassischen Fall zu programmieren und ihn dann versuchen zu optimieren, meist liegt das Problem an anderer Stelle. Falls es wirklich am Baum liegen sollte und Du als Blätter nur Stringdaten hast, warum legst Du diese nicht in eine Datenbank und setzt zu Traversierung Stored Procedures ein, damit hast Du aus PHP dei Zugriffe aus dem Baum in die Datenbank verschoben, die meist etwas performanter arbeitet. HTH Phil Zitieren
Aiun Geschrieben 3. Februar 2008 Autor Geschrieben 3. Februar 2008 danke für die Antwort. 'sphere' ist der Name der API, habe ich in dem Beispiel verwendet, da es derzeit nur Konfigurationsscripte gibt, die direkt vom Wurzelknoten aus gesetzt werden. Im nächsten Schritt wird es auch Scripte geben, die nur innerhalb einer CMS-Seite gültig sind, also dem Baum unterhalb ihres Astes zugefügt werden. In diesem Script ist dann die CMS-View die Rootnode. Ich suche nach Beschleunigungsmöglichkeiten, was nicht heißen muss das es sie gibt ^^ eine Flache struktur funktioniert nicht, da die Pfade ja unendlich tief sein können. Es kann sein das ich einen Ast auf Tiefe 3 als Blatt anspreche (methode 'getString()') er aber gar kein Blatt ist, das wird dann von getString() geregelt. naja, ich denke es wird einfach zeit brauchen den algorythmus zu optimieren. Danke soweit. Zitieren
Empfohlene Beiträge
Dein Kommentar
Du kannst jetzt schreiben und Dich später registrieren. Wenn Du ein Konto hast, melde Dich jetzt an, um unter Deinem Benutzernamen zu schreiben.