04.03.2007
Array bei einem bestimmten Eintrag teilen
Eigentlich vermute ich ja, dass es hier noch einen besseren Weg gibt, nur habe ich diesen nicht gefunden. Daher ist die folgende Lösung momentan das Beste was ich machen kann, wenn ich z.B. einen Link in eine Liste einfügen will (Stichwort Navigation).
<?$allObst = array(Apfel, Kirsche, Birne, Pflaume, Mirabelle, Granatapfel, Banane, Ananas);$itemx = "Pflaume"; // oder z.B. $_GET['seitenname']$keyx = array_search($itemx, $allObst)+1;$allObstPartOne = array_chunk($allObst, $keyx, true);$allObstPartOne = $allObstPartOne[0];$allObstPartTwo = array_chunk(array_reverse($allObst), count($allObst)-$keyx) ;$allObstPartTwo = array_reverse($allObstPartTwo[0]);funktion () {...}; //e.g. insert another fruit (create new item)$allObstnew = array_merge($allObstPartOne, $NewItemX, $allObstPartTwo);?>
Die verwendeten Funktionen:
- array_search($needle, $stack)
Position im Array des gesuchten Eintrags - array_chunk($stack, $Itemcount, true)
Kreiiert lauter kleine UnterArrays mit der vorgegebenen Anzahl von Einträgen + Rest - array_reverse($stack)
dreht die Reihenfolge um - array_merge($Teil1, $teil2);
Fügt die Teile wieder zusammen.
Also ganz einfach.
x Einträge – Einträge bis Item = Anzahl Einträge des Rests. Rest von hinten gezählt, Bingo. Und weil PHP bei Null und nicht bei eins anfängt zu zählen, darf man nicht vergessen, die Anzahl der Eintäge um ± 1 zu korrigieren.
Update: Oder man durchläuft den Array per foreach() … tömmtölömm … und fügt ein, sobald die Bedingung val==$itemx zutrifft. Danke an Mathias Bank für den Kommentar. Warum einfach, wenn es auch kompliziert geht (wobei meine Methode plastischer ist, wie mit Körbchen und echtem Obst in echter Schwerst-Arbeit) … *hihihi*
.
foreach($allObst as &$key=>&$val) {if ($val==$itemx) {$newObst[$key]=$newItemX;}else {$newObst[$key] = $val;}}
Zitat Mathias Bank: $key und $val sind Referenzen, es muss also keine Kopie erstellt werden, das spart Zeit
Wo er recht hat, hat er recht.
Update 2: Ongoing Process. Nachdem der im Kommentar kurz hingeschriebene Code-Schnipsel den Eintrag ersetzt und nicht ergänzte, war ich wieder am rätseln und probieren
foreach($allObst as &$key=>&$val) {if ($val==$itemx) {$newObst[$key].= $newItemX;}else {$newObst[$key] = $val;}}
Aaaah! Man muss nur darauf achten, dass der Eintrag ergänzt (man beachte den Punkt vorm Gleichheitszeichen) und auf die Delimiter sollte man achten und diesen mitschreiben.
Filed under: Programmierung
3 Comments
March 4th, 2007 at 11:35
Also wenn ich das richtig sehe, dann willst du praktisch ein Element ersetzen, aber die Keys beibehalten.
Hier stellt sich die erste Frage: warum willst du die Keys beibehalten: Haben Sie wirklich eine Bedeutung? Macht spontan nicht den Eindruck weil sie von PHP vergeben werden.
Dann zu deinem Script. Zählen wir mal, wie oft das Script das gesamte Array durchgeht (im schlimmsten Fall):
array_search: +1
array_chunk: 0 (wir gehen hier mal aus, es wird gleich am Anfang gefunden)
array_reverse: +1
array_chunk: +1 (es muss jetzt ganz durchgeschaut werden)
array_reverse: +1
array_merge: +1
Wir laufen also insgesamt 5 mal durch das Array. Egal wie performant das programmiert wird, wir müssen 5 mal durch.
Deshalb würde ich an deiner Stelle einfach direkt eine Kopie des Arrays erstellen:
foreach($allObst as &$key=>&$val) {
//$key und $val sind Referenzen, es muss also keine Kopie erstellt werden, das spart Zeit
if ($val==$itemx) $newObst[$key]=$newItemX;
else $newObst[$key] = $val;
}
Jetzt laufen wir nur einmal das Array durch. Das dürfte wesentlich performanter sein. Dass wir jetzt eine Kopie erzeugen ist nicht problematisch, dass machen die array-Funktionen jeweils auch.
March 4th, 2007 at 12:02
Der Key war mir ziemlich schnurz. Ich bekomme bei Arrays nur immer noch einen Knoten im Kopp. Außerdem stehe ich mit foreach() irgendwie auf Kriegsfuß. Ich wollte nur meine Navigation nicht mehr unten sondern mittendrin ergänzen.
Wobei ich bei kurzen Listen kein Problem habe, wenn diese 5 Mal durchlaufen werden müssen, weil es immer noch außerhalb meiner Wahrnehmung liegt.
March 7th, 2007 at 15:38
Schön, helfen zu können
Vielleicht noch als weiterer Tipp: Da du jetzt auf Referenzen arbeitest, bedeutet das nichts anderes, als dass du auf dem Original arbeitest (der Speicher verweist nur -> Referenz). Damit kann man das ganze sehr elegant lösen. Ich lass dabei jetzt den key weg, weil du den ja nicht brauchst:
foreach($allObst as &$val) {
if ($val==$itemx) {
$val.= $newItemX;
}
}
Wie du siehst, arbeite ich direkt auf $val. Durch die Referenz arbeite ich dadurch direkt auf dem Array und muss nicht auf das Array-Objekt verweisen.
$newObst[$key] ist eigentlich nur notwendig, wenn du nicht mit Referenzen arbeitest (gibt ja evtl. Gründe dafür).