Update eines arrays
Piet
- php
Hallo,
mit folgenden Zeilen, möchte ich bestimmte Einträge in einem array korrigieren.
Die echo-Anweisung zeigt das korr. Element richtig an, im array ist es aber dann nicht korrigiert.
Was mache ich falsch?
foreach ($fields as $field)
{
if (......)
$field = $field . $zusatz;
echo $field . "<br>";
}
print_r ($fields);
Was mache ich falsch?
Du brauchst eine Referennz auf $filed.
foreach ($fields as $field)
{
if (......)
$field = $field . $zusatz;
echo $field . "<br>";
}print_r ($fields);
~~~php
foreach ($fields as &$field){/* ... */}
Online Beispiel:
http://codepad.org/K6GzcOaZ
Du brauchst eine Referennz auf $filed.
foreach ($fields as &$field){/* ... */}
Danke, diese einfache Änderung funktioniert.
Jetzt aber ein weiteres Problem:
Neben der Änderung möchte ich abhängig von einer Bedingung auch Elemente aus dem array löschen. Gefunden habe ich unset.
Also bin ich munter ans Werk gegangen und habe geschrieben:
~~~php
foreach ($fields as &$field)
{
if (......)
$field = $field . $zusatz;
elseif (....)
unset($field);
}
print_r ($fields);
Der Eintrag ist aber leider nicht gelöscht.
Woran liegt dies?
Danke Euch
Piet
Woran liegt dies?
unset() will wissen was es löschen soll. Mich wundert, dass Du keine Notizen empfängst. Auch wenn meine - flexible, lesbare, verständliche, funktionierende und nicht mit Nachteilen behaftete - Lösung wieder Widerspruch ernten wird: Hier die allfällige Erweiterung:
<?php
$fields[1]='Hallo';
$fields[2]='weg damit';
$fields['foo']='Hallo';
$fields['bar']='Hallo';
foreach (array_keys($fields) as $key) {
if ('weg damit' == $fields[$key]) {
unset($fields[$key]);
} else {
$fields[$key] .= ' Welt!';
}
}
print_r ($fields);
?>
~> php test.php
Array
(
[1] => Hallo Welt!
[foo] => Hallo Welt!
[bar] => Hallo Welt!
)
Variante nach dedlfix:
<?php
$fields[1]='Hallo';
$fields[2]='weg damit';
$fields['foo']='Hallo';
$fields['bar']='Hallo';
foreach ($fields as $key => $value) {
if ('weg damit' == $value) {
unset($fields[$key]);
} else {
$fields[$key] .= ' Welt!';
}
}
print_r ($fields);
?>
~> php test.php
Array
(
[1] => Hallo Welt!
[foo] => Hallo Welt!
[bar] => Hallo Welt!
)
Tach!
unset() will wissen was es löschen soll. Mich wundert, dass Du keine Notizen empfängst.
Da kommt keine, weil es dazu keinen Grund gibt. Das unset($field) löscht $field, was in unserem Fall eine Referenz auf einen Array-Eintrag ist. Beim nächsten foreach-Durchlauf wird $field wieder als neue Referenz angelegt. Wenn nach dem unset() im restlichen Schleifenkörper noch Lesezugriffe auf $field kämen, dann wäre eine Notice gerechtfertigt.
dedlfix.
Auch wenn meine - flexible
Auch meine Variante ist flexibel
lesbare
*schwerer lesbare
verständliche
und umständliche
funktionierende
da hab ich keine Einwand
und nicht mit Nachteilen behaftete
mal abgesehen von Laufzeit und Speicherbedarf
- Lösung wieder Widerspruch ernten wird
Und war das Genugtuung?
Hi,
Deinen Vorschlag
<?php
$fields[1]='Hallo';
$fields[2]='weg damit';
$fields['foo']='Hallo';
$fields['bar']='Hallo';foreach (array_keys($fields) as $key) {
if ('weg damit' == $fields[$key]) {
unset($fields[$key]);
} else {
$fields[$key] .= ' Welt!';
}
}
print_r ($fields);
?>
>
konnte ich bei mir erfolgreich umsetzen.
Ob dies die beste Variante ist, kann ich nicht beurteilen.
Aber wie bekomme ich jetzt die Lücken raus?
Gibt es hierfür eine Funktion oder muss ich ein neues array erzeugen?
Gruß
Piet
Tach!
Deinen Vorschlag
konnte ich bei mir erfolgreich umsetzen.
Welche Probleme hattest du denn mit den anderen Vorschlägen?
Aber wie bekomme ich jetzt die Lücken raus?
Welche Lücken? Hast du nummerierte Keys? Und wenn ja, warum brauchst du die lückenlos? Für das foreach jedenfalls nicht, das iteriert problemlos über alles möglichen Arrays, egal wie die Keys verteilt sind oder aussehen. Wie auch immer, es gibt array_values(), das erstellt ein neues Array nur aus den Werten und nummeriert die Keys von 0 an durch.
dedlfix.
Welche Probleme hattest du denn mit den anderen Vorschlägen?
Ich habe nicht alle durchprobiert - aus Verständnisgründen.
Aber wie bekomme ich jetzt die Lücken raus?
Welche Lücken? Hast du nummerierte Keys? Und wenn ja, warum brauchst du die lückenlos?
Wenn ich später über eine do-Schleife darüber gehe, kommt der Fehler, dass (sinngemäß): index x nicht existiert
Wenn ich später über eine do-Schleife darüber gehe, kommt der Fehler, dass (sinngemäß): index x nicht existiert
Dir fehlen offensichtlich Grundlagen zu Arrays und Konstrollstrukturen.
Tach!
Welche Probleme hattest du denn mit den anderen Vorschlägen?
Ich habe nicht alle durchprobiert - aus Verständnisgründen.
Dann solltest du dir unbedingt die von PHP vorgesehene und übliche Version
foreach ($array as $key => $value)
anschauen und in deinem Fall die mit der Referenz
foreach ($array as $key => &$value)
Aber wie bekomme ich jetzt die Lücken raus?
Welche Lücken? Hast du nummerierte Keys? Und wenn ja, warum brauchst du die lückenlos?
Wenn ich später über eine do-Schleife darüber gehe, kommt der Fehler, dass (sinngemäß): index x nicht existiert
Warum willst du denn später mit do-while darübergehen? Was du vorhast, lässt sich sicher auch mit foreach erledigen, das sich an solchen Lücken nicht stört. Eine Abbruchbedingung kannst du auch innerhalb foreach ans Ende schreiben: if (bedingung) break;
dedlfix.
Hallo dedlfix,
Welche Probleme hattest du denn mit den anderen Vorschlägen?
Ich habe nicht alle durchprobiert - aus Verständnisgründen.Dann solltest du dir unbedingt die von PHP vorgesehene und übliche Version
foreach ($array as $key => $value)
anschauen und in deinem Fall die mit der Referenz
foreach ($array as $key => &$value)
Mit der jetzt realisierten (umständlichen) Version kann ich einen Wert ändern oder löschen.
Die anderen Vorschläge beziehen sich, falls ich es richtig verstanden habe
entweder auf das Update:
foreach ($array as $key => &$value)
oder auf das Löschen:
foreach ($array as $key => &$value)
Wie ich beides in einer loop machen kann habe ich nicht gefunden (übersehen?)
Für einen entsprechenden Tipp wäre ich dankbar
Gruß
Piet
Wie ich beides in einer loop machen kann habe ich nicht gefunden (übersehen?)
Genau wie Freds Lösung auch. Hier ein Beispiel
Genau wie Freds Lösung auch. Hier ein Beispiel
Super, danke!
Tach!
Mit der jetzt realisierten (umständlichen) Version kann ich einen Wert ändern oder löschen.
Die anderen Vorschläge beziehen sich, falls ich es richtig verstanden habe
entweder auf das Update:
foreach ($array as $key => &$value)
oder auf das Löschen:
foreach ($array as $key => &$value)
Nochmal zum Verständnis der Problematik. Die einfachste Variante von foreach liefert dir nur den Wert des aktuellen Array-Element.
1a) foreach ($array as $value)
In $value steht eine Kopie dieses Wertes. Deswegen nützt es dir nichts, wenn du diese Kopie änderst oder löschst, weil du darüber weder den eigentlichen Wert ändern noch das gesamte Element löschen kannst. Du benötigst für das eigentliche Element den Key, um über $array[$key] direkt den Wert ändern zu können oder auch das Element mit unset() zu entfernen. Deswegen gibt es die zweite foreach-Variante:
2a) foreach ($array as $key => $value)
Diese liefert dir ebenfalls den Wert als Kopie und zusätzlich den Key. Damit hast du jetzt die Möglichkeiten über $value nur lesend auf den Wert zuzugreifen und über $array[$key] schreibend und löschen, aber auch lesend, wenn du willst. Doch für das Lesen ist jedoch $value einfacher als $array[$key] zu notieren.
Im Laufe der Zeit wurde in PHP dann noch die Variante mit der Referenz hinzugefügt.
1b) foreach ($array as &$value)
Damit ist $value nun keine Kopie mehr sondern ein direkter Verweis auf den Wert. Darüber kannst du den Wert direkt mit einer Zuweisung an $value ändern. Aber du kannst damit nicht das Element löschen, weil du mit unset($value) nur $value selbst löschst, also nur den Verweis, aber nicht den eigentlichen Wert. Zum Löschen brauchst du immer noch den Key. Und dafür gibt es dann die Key-Value-Variante von foreach zusammen mit der Referenz-statt-Kopie-Schreibweise.
2b) foreach ($array as $key => &$value)
Du kannst nun über $array[$key] lesend, schreibend und löschend zugreifen, über $value immerhin noch lesend und schreibend.
Wie ich beides in einer loop machen kann habe ich nicht gefunden (übersehen?)
Diese letzte Variante ist also das non-plus-ultra, aber mit Variante 2a kämest du auch schon ans Ziel.
Das sind die von PHP direkt vorgesehenene Wege, foreach auf ein Array anzuwenden. Da 1UnitedPower nicht wusste (und ich hätte es zunächst wohl auch nicht anders gemacht), dass du nicht nur schreibenden Zugriff benötigst, sondern auch löschen willst, war Variante 1b zunächst ausreichend, sonst wäre sicher gleich Variante 2a oder 2b ins Spiel gekommen. - Fred hat hingegen einen ungewöhnlichen Weg gewählt. Die Bedingung, um lesend, schreibend und löschend zugreifen zu können, ist ja der Key, und da die Funktion array_keys() alle Keys als (ein neues) Array liefert, nahm er diese Funktion. Die muss aber zunächst einmal selbst über das Array laufen, alle Keys einsammeln und sie in einem neuen Array ablegen. Dann läufst du mit foreach über dieses Array und über $array[$key] stehen dir alle Möglichkeiten offen. Es ist aber mit den direkten Varianten 2a und 2b nicht notwendig, zweimal über das Array zu laufen, weil diese gleich beim ersten/einzigen/eigentlichen Durchlauf alle Notwendige bereitstellen.
dedlfix.
Danke für diese Erläuterung!
Tach!
foreach ($fields as &$field){/* ... */}
unset($field);
Der Eintrag ist aber leider nicht gelöscht.
Damit löschst du nur die Referenz, nicht den eigentlichen Wert, auf den $field zeigt. Zum Löschen brauchst du den richtigen Eintrag im Array. Du kannst dafür die Variante
foreach ($array as $key => $value)
nehmen und dann
unset($array[$key]);
dedlfix.
Moin!
Was mache ich falsch?
foreach ($fields as $field)
{
if (......)
$field = $field . $zusatz;
echo $field . "<br>";
}print_r ($fields);
Du änderst nicht den Array fields sondern nur die Variable field.
Du musst die Schlüssel des Arrays ermitteln und dann die Elemente damit adressieren:
"selbsterklärend:"
~~~php
<?php
$fields[1]='Hallo';
$fields[2]='Hallo';
$fields['foo']='Hallo';
$fields['bar']='Hallo';
$arKeys=[link:http://de3.php.net/manual/de/function.array-keys.php@title=array_keys]($fields);
foreach ($arKeys as $varKey) {
$fields[$varKey] .= ' Welt!';
}
print_r ($fields);
?>
~> php test.php
Array
(
[1] => Hallo Welt!
[2] => Hallo Welt!
[foo] => Hallo Welt!
[bar] => Hallo Welt!
)
Eine Zeile kürzer:
<?php
$fields[1]='Hallo';
$fields[2]='Hallo';
$fields['foo']='Hallo';
$fields['bar']='Hallo';
foreach (array_keys($fields) as $key) {
$fields[$key] .= ' Welt!';
}
print_r ($fields);
?>
Tach!
Du änderst nicht den Array fields sondern nur die Variable field.
Du musst die Schlüssel des Arrays ermitteln und dann die Elemente damit adressieren:
Ja. Nein, müssen muss er das nicht. Eine Lösung stand ja schon da: Referenzieren.
Eine Zeile kürzer:
foreach (array_keys($fields) as $key) {
Selbst wenn man das über die Keys machen will, ist das zu umständlich. Es gibt
foreach ($array as $key => $value)
da wird der Key gleich mitgeliefert.
dedlfix.
Tach!
Post!
Selbst wenn man das über die Keys machen will, ist das zu umständlich. Es gibt
foreach ($array as $key => $value)
da wird der Key gleich mitgeliefert.
Wow!
Eine andere Zeile!
foreach ($array as $key => $value) {
statt:
foreach (array_keys($array)as $key) {
und dann auch noch statt dem wahnsinnig umständlichen
$array[$key] .=' Welt';
nur ein
$array[$key] .=' Welt';
Da wird der Interpreter aber vor Freude aus dem Häuschen sein, dass er es nicht so UMSTÄNDLICH vorgelegt bekommt.
fred
Tach!
Selbst wenn man das über die Keys machen will, ist das zu umständlich. Es gibt
foreach ($array as $key => $value)
da wird der Key gleich mitgeliefert.
Wow!
Eine andere Zeile!
Die "andere Zeile" bewirkt, dass nur einmal über das Array iteriert werden muss. Mit deiner Variante müssen zuerst alle Keys eingesammelt werden, um dann über sie zu laufen.
und dann auch noch statt dem wahnsinnig umständlichen
$array[$key] .=' Welt';
nur ein
$array[$key] .=' Welt';
Zum Schreiben braucht man in beiden Varianten $array[$key], aber für das reine Lesen wäre $value vorhanden und einfacher handzuhaben. Damit fällt je Verwendung eine Auflösung des Ausdrucks $array[$key] und damit PHP-intern eine Suche im Array nach dem Schlüssel weg und der Leser hat es auch etwas einfacher.
Zudem kann man diese Key-Value-Foreach-Schleife auch noch mit der Referenz kombinieren
foreach ($array as $key => &$value)
So kann man direkt über $value das Element lesen und schreiben und nur zum Löschen wird $array[$key] benötigt.
Da wird der Interpreter aber vor Freude aus dem Häuschen sein, dass er es nicht so UMSTÄNDLICH vorgelegt bekommt.
Dem wird das egal sein, die Laufzeitunterschiede sind sicher nicht spürbar. Es geht hier mehr um die Lesbarkeit. Der Funktionsaufruf ist unüblich, weil es eine direkte Lösung gibt. Das bremst vor allem beim Lesen des Codes.
dedlfix.
Du musst die Schlüssel des Arrays ermitteln und dann die Elemente damit adressieren
Viel zu umständlich. Wozu gibts denn Referenzen?
Moin!
Du musst die Schlüssel des Arrays ermitteln und dann die Elemente damit adressieren
Viel zu umständlich. Wozu gibts denn Referenzen?
Um die Programme unverständlicher und fehleranfälliger zu machen.
Dein Beispiel: http://codepad.org/deGcFVGR
<?php
header("Content-Type: text/plain");
$fields = array();
$fields[] = "Foo";
$fields[] = "FooFoo";
foreach ($fields as &$field)
{
$field .= ' Bar';
}
print_r ($fields);
$field = "fail";
print_r($fields);
- Sven Rautenberg
Um die Programme unverständlicher und fehleranfälliger zu machen.
Für diejenigen, die Referenzen nicht verstehen.
Dein Beispiel: http://codepad.org/deGcFVGR
Dein Beispiel: http://codepad.org/YdvmEIrj