Gedrag foreach loop
Ik vraag mij af wat er fout gaat met volgende code.
De output van:
for ($j = 1; $j <= 6; $j++)
{
print "index 6 3 : " . $course_list[6][3] . "\n";
}
is :
index 6 3 : 5
index 6 3 : 5
index 6 3 : 5
index 6 3 : 5
index 6 3 : 5
index 6 3 : 5
index 6 3 : 5
Dat is correct. In het block wordt $j of $var niet gebruikt, de geprinte lijn is dan ook steeds hetzelfde.
De output van :
foreach ($course_list as $j => $lcourse)
{
print "index 6 3 : " . $course_list[6][3] . "\n";
}
is :
index 6 3 : 1
index 6 3 : -1
index 6 3 : 2
index 6 3 : 3
index 6 3 : 4
index 6 3 : 4
Dat snap ik niet. de waarden zijn die van $course_list[$j][3], behalve voor $j = 6, dat zou 5 moeten zijn, zoals in het eerste voorbeeld.
Maar ik verwachtte dat de output van de twee voorbeelden hetzelfde zou zijn.
Wat mis ik hier ?
Alvast bedankt,
Luc.
Wil je daar niet ergens een $j in hebben?
Ivo P op 11/11/2024 09:25:49:
klopt die code die je hier plaatst? Er staat overal [6][3]
Wil je daar niet ergens een $j in hebben?
Wil je daar niet ergens een $j in hebben?
Ja, dat is het net :-). Het is omdat de waarden niet klopten als $j = 6 dat ik verder ben beginnen kijken.
De statements en output zijn dus wel degelijk uitgevoerd zoals afgebeeld.
Het statement in de foreach loop bevat $j niet, en de print is dus 'statisch', en geeft toch verschillende waarden, alsof er ipv 6 $j zou staan, behalve voor de laatste, die zou 5 moeten zijn ipv 4, zoals in de for loop het geval is.
Tussen de twee loops, werd er niets aan de array gewijzigd, en de volgorde van de statements heeft ook geen belang.
Dat voorafgaand aan dit statement $course_list werd aangepast binnen een foreach($course_list ...) heeft er mee te maken, maar dan nog kan ik dit niet verklaren.
Ik heb nu alle foreach loopen verwijderd en vervangen door klassieke for loopen op index.
Mvg,
Luc.
Gewijzigd op 11/11/2024 15:17:40 door Luc Vanderveurst
Als er 6 elementen in jouw array zitten, dan is het laatste element dus key 5.
Code (php)
Maar als je 2 dimensies hebt, dan in $vrucht ook weer een array. Of wil je steeds element "3" van de 2e laag hebben?
Door steeds hard 6 en 3 in je code te zetten, wordt je verhaal niet veel duidelijker.
Twee loop statements waarbij het statement in de loop niet wordt beinvloed door de variabelen in de loop, geven verschillend resultaat. En dat vind ik gek en kan ik niet verklaren.
Post dan nog eens de complete code met de beide loops? Inclusief de inhoud van $course_list.
Luc Vanderveurst op 12/11/2024 13:46:19:
Twee loop statements waarbij het statement in de loop niet wordt beinvloed door de variabelen in de loop, geven verschillend resultaat. En dat vind ik gek en kan ik niet verklaren.
Een iterator heeft een key (of pointer) die verandert wanneer je de elementen langsloopt.
Daar kun je last van hebben wanneer je niet beseft dat die verplaatsing achter de schermen plaatsvindt of wanneer je zelf bewust de key verplaatst tijdens het itereren.
Het kan ook tot bugs leiden die op het eerste gezicht onverklaarbaar lijken. Staat de key bijvoorbeeld op het laatste element in een array, dan lijk je geen elementen meer te kunnen lezen, ook al weet je dat de array meer data bevat. Dit soort bugs treedt typisch op als je probeert meer dan één operatie uit te voeren met één iterator, bijvoorbeeld in een loop zoals een foreach.
Volgens zijn eerste post leveren deze twee regels:
Luc Vanderveurst op 10/11/2024 18:42:12:
print "index 6 3 : " . $course_list[6][3] . "\n";
print "index 6 3 : " . $course_list[6][3] . "\n";
print "index 6 3 : " . $course_list[6][3] . "\n";
die in de verschillende foreach() staan verschillende output.
Lijkt mij onmogelijk maar het is de vraag: Waardoor?
Luc Vanderveurst op 11/11/2024 15:12:07:
Ik heb nu alle foreach loopen verwijderd en vervangen door klassieke for loopen op index.
Maar zoals Ozzie aangeeft: daar kunnen we slechts naar raden als de topicstarter alleen de vereenvoudigde code post die hij begrijpt en niet de code die operaties uitvoert met de iterator of elementen in de iterator.
Het gedrag van een iterator is niet vreemd als je maar weet hoe een iterator werkt.
Ozzie PHP op 12/11/2024 15:00:15:
Post dan nog eens de complete code met de beide loops? Inclusief de inhoud van $course_list.
Hier is de code voor inhoud en foreach loop :
Code (php)
1
2
3
4
5
2
3
4
5
print_r($course_list);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
En dit is de output :
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
Array
(
[1] => Array
(
[0] => AMUSE
[1] => Wortel tartaar
[2] => 32
[3] => 1
)
[2] => Array
(
[0] => hoofdgerecht
[1] => Voeg de rest van de ingredi?nten toe en laat zo lang als mogelijk tegen de kook aan trekken
[2] => 51
[3] => -1
)
[3] => Array
(
[0] => VOORGERECHT
[1] => Krokante gamba`s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette
[2] => 61
[3] => 2
)
[4] => Array
(
[0] => TUSSENGERECHT
[1] => Gemarineerde zalm, boemboe Bali, wortel en gember
[2] => 80
[3] => 3
)
[5] => Array
(
[0] => HOOFDGERECHT
[1] => Kiprouleau met ras el hanout-roomsaus
[2] => 109
[3] => 4
)
[6] => Array
(
[0] => NAGERECHT
[1] => bramencake met munt en ijs van zoute amandelen
[2] => 126
[3] => 5
)
)
1 1
2 -1
3 2
4 3
5 4
6 4
(
[1] => Array
(
[0] => AMUSE
[1] => Wortel tartaar
[2] => 32
[3] => 1
)
[2] => Array
(
[0] => hoofdgerecht
[1] => Voeg de rest van de ingredi?nten toe en laat zo lang als mogelijk tegen de kook aan trekken
[2] => 51
[3] => -1
)
[3] => Array
(
[0] => VOORGERECHT
[1] => Krokante gamba`s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette
[2] => 61
[3] => 2
)
[4] => Array
(
[0] => TUSSENGERECHT
[1] => Gemarineerde zalm, boemboe Bali, wortel en gember
[2] => 80
[3] => 3
)
[5] => Array
(
[0] => HOOFDGERECHT
[1] => Kiprouleau met ras el hanout-roomsaus
[2] => 109
[3] => 4
)
[6] => Array
(
[0] => NAGERECHT
[1] => bramencake met munt en ijs van zoute amandelen
[2] => 126
[3] => 5
)
)
1 1
2 -1
3 2
4 3
5 4
6 4
Gewijzigd op 14/11/2024 00:56:48 door Luc Vanderveurst
Ik krijg namelijk gewoon:
Testscript:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$course_list = array(
1 => array('AMUSE', 'Wortel tartaar', 32, 1),
2 => array('hoofdgerecht', 'Voeg de rest van de ingrediënten toe en laat zo lang als mogelijk tegen de kook aan trekken', 51, -1),
3 => array('VOORGERECHT', 'Krokante gamba\'s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette', 61, 2),
4 => array('TUSSENGERECHT', 'Gemarineerde zalm, boemboe Bali, wortel en gember', 80, 3),
5 => array('HOOFDGERECHT', 'Kiprouleau met ras el hanout-roomsaus', 109, 4),
6 => array('NAGERECHT', 'bramencake met munt en ijs van zoute amandelen', 126, 5)
);
print_r($course_list);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
?>
$course_list = array(
1 => array('AMUSE', 'Wortel tartaar', 32, 1),
2 => array('hoofdgerecht', 'Voeg de rest van de ingrediënten toe en laat zo lang als mogelijk tegen de kook aan trekken', 51, -1),
3 => array('VOORGERECHT', 'Krokante gamba\'s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette', 61, 2),
4 => array('TUSSENGERECHT', 'Gemarineerde zalm, boemboe Bali, wortel en gember', 80, 3),
5 => array('HOOFDGERECHT', 'Kiprouleau met ras el hanout-roomsaus', 109, 4),
6 => array('NAGERECHT', 'bramencake met munt en ijs van zoute amandelen', 126, 5)
);
print_r($course_list);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
?>
Zie: https://3v4l.org/LqTSf#v8.3.13
of $course_list[6][3] is dan $lcourse[3]
Of in de lus gebeurt meer, waardoor de inhoud van $course_list intussen steeds aangepast wordt. (hergebruik van een naam van een variabele?)
Maar, ... ik heb nog wat gevonden.
Eerst wordt in arrea $course_list[$j], [0],[1] en [2] opgevuld (dus $course_list[$j][$k] met k 0 , 1 en 2).
Nadien wordt in een foreach loop index 3 opgevuld.
In die foreach groep staat : foreach($course_list as $j => &$lcourse)
dus met een & voor om de waarden te kunnen wijzigen.
Iets waarvan ik nadien afgestapt ben en de wijzingen (aanpassen van $course_list[$j][3]) via $course_list[$j] heb uitgevoerd, dus die '&' was overbodig.
Maar dat is wel de boosdoener. Zonder die & krijg ik wel het goede resultaat.
De print_r toont wel de juiste data, dus ik blijf het vreemd vinden dat die loop (om de data op te vullen) een impact heeft op de data in een andere loop (om de data te tonen).
Toevoeging op 14/11/2024 14:40:05:
Als je in :
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
<?php
$course_list = array(
1 => array('AMUSE', 'Wortel tartaar', 32, 1),
2 => array('hoofdgerecht', 'Voeg de rest van de ingrediënten toe en laat zo lang als mogelijk tegen de kook aan trekken', 51, -1),
3 => array('VOORGERECHT', 'Krokante gamba\'s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette', 61, 2),
4 => array('TUSSENGERECHT', 'Gemarineerde zalm, boemboe Bali, wortel en gember', 80, 3),
5 => array('HOOFDGERECHT', 'Kiprouleau met ras el hanout-roomsaus', 109, 4),
6 => array('NAGERECHT', 'bramencake met munt en ijs van zoute amandelen', 126, 5)
);
print_r($course_list);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
?>
$course_list = array(
1 => array('AMUSE', 'Wortel tartaar', 32, 1),
2 => array('hoofdgerecht', 'Voeg de rest van de ingrediënten toe en laat zo lang als mogelijk tegen de kook aan trekken', 51, -1),
3 => array('VOORGERECHT', 'Krokante gamba\'s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette', 61, 2),
4 => array('TUSSENGERECHT', 'Gemarineerde zalm, boemboe Bali, wortel en gember', 80, 3),
5 => array('HOOFDGERECHT', 'Kiprouleau met ras el hanout-roomsaus', 109, 4),
6 => array('NAGERECHT', 'bramencake met munt en ijs van zoute amandelen', 126, 5)
);
print_r($course_list);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
?>
foreach($course_list as $j => $lcourse) vervangt door foreach($course_list as $j => &$lcourse)
dan krijg je denk ik ook het foute resultaat.
Ik krijg het foute resultaat ook zonder die &, maar dus omdat een eerdere foreach loop die & wel bevatte.
Zet direct na die foreach loop waarin je & gebruikt eens unset($lcourse). Dus als volgt:
Probeer het dan nog eens.
En, heb je het al geprobeerd?
Het was er nog niet van gekomen het antwoord opnieuw samen te stellen.
Ozzie PHP op 14/11/2024 20:46:50:
Je hebt dus niet de complete code gepost. Met & maak je een 'by reference' koppeling.
Klopt, daar bleek niet uit hoe de array was aangepast. Het hele programma posten zou ook niet overzichtelijk geweest zijn, de werking is data-driven en gebaseerd op externe files, ik had enkel gepost wat ik dacht dat relevant was, en dat was dus niet genoeg.
Quote:
Voortbouwend op het voorbeeld wat Ward heeft gepost:
Quote:
Code (php)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
<?php
$course_list = array(
1 => array('AMUSE', 'Wortel tartaar', 32, 1),
2 => array('hoofdgerecht', 'Voeg de rest van de ingrediënten toe en laat zo lang als mogelijk tegen de kook aan trekken', 51, -1),
3 => array('VOORGERECHT', 'Krokante gamba\'s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette', 61, 2),
4 => array('TUSSENGERECHT', 'Gemarineerde zalm, boemboe Bali, wortel en gember', 80, 3),
5 => array('HOOFDGERECHT', 'Kiprouleau met ras el hanout-roomsaus', 109, 4),
6 => array('NAGERECHT', 'bramencake met munt en ijs van zoute amandelen', 126, 5)
);
print_r($course_list);
foreach($course_list as $j => &$lcourse)
{
$i = 1; # doe iets
}
# unset($lcourse);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
?>
$course_list = array(
1 => array('AMUSE', 'Wortel tartaar', 32, 1),
2 => array('hoofdgerecht', 'Voeg de rest van de ingrediënten toe en laat zo lang als mogelijk tegen de kook aan trekken', 51, -1),
3 => array('VOORGERECHT', 'Krokante gamba\'s met Aziatisch aangemaakte groentesalade en een oosterse sesam vinaigrette', 61, 2),
4 => array('TUSSENGERECHT', 'Gemarineerde zalm, boemboe Bali, wortel en gember', 80, 3),
5 => array('HOOFDGERECHT', 'Kiprouleau met ras el hanout-roomsaus', 109, 4),
6 => array('NAGERECHT', 'bramencake met munt en ijs van zoute amandelen', 126, 5)
);
print_r($course_list);
foreach($course_list as $j => &$lcourse)
{
$i = 1; # doe iets
}
# unset($lcourse);
foreach($course_list as $j => $lcourse)
{
print "$j " . $course_list[6][3] . "\n";
}
?>
geeft fout resultaat met de unset in kommentaar:
Quote:
1 1
2 -1
3 2
4 3
5 4
6 4
2 -1
3 2
4 3
5 4
6 4
en goed resultaat met de unset uit kommentaar:
Quote:
1 5
2 5
3 5
4 5
5 5
6 5
2 5
3 5
4 5
5 5
6 5
Dus die unset lost inderdaad het probleem op. Thanks.
Wat ook het probleem oplost is:
- in de tweede foreach loop ook een call by reference zetten
- in de tweede foreach loop een andere variabele gebruiken.
Gewijzigd op 20/11/2024 22:35:51 door Luc Vanderveurst
Bedankt voor je reactie. Dan zal het dus gelegen hebben aan de call by reference.