while conditie met array?
@SanThe. Nee, zoals Erwin het doet klopt het. Dat was wat ik bedoelde.
Oftewel de plusjes voor de variabelen worden eerst uitgevoerd voor het echoen.
Wat bedoel je daarmee Willem? >> aangezien PHP feitelijk gezien geen arrays kent
Stel je hebt een array van 10 integers en een integer is 4 bytes. Om het eerste element $array[0] te vinden neem je dan het beginadres van de datastructuur en telt er 0x4 bytes bij op. Het zevende element is dus te vinden op 6x4 bytes vanaf het begin.
In PHP is een array eigenlijk een linked list. Als je een element toevoegt aan de array, zal in het laatste element een pointer worden opgenomen naar het nieuwe element. Als je $array[3] wilt hebben, begint PHP te zoeken bij het eerste element van de array. Hij vergelijkt de array key met de key die jij zoekt, en als die niet overeenkomen, gaat hij via de pointer naar het volgende element. Zo zoekt hij net zolang tot hij de juiste key gevonden heeft.
Het gevolg hiervan is dat wanneer je een array afloopt met while($array[$i]){$i++;} de tijd die je while-loop nodig heeft kwadratisch (!) toeneemt met het aantal elementen in je array. Een foreach-loop heeft in dit geval een lineair verband. Een array is een datastructuur waarbij elk element een vaste, berekenbare, offset heeft vanaf het begin van het eerste element.
While *stopt* wanneer er geen element meer met color is, foreach zou hem gewoon *overslaan*. Om de while loop goed te kunnen gebruiken zou er dus een break in de else statement moeten. Ik weet niet of Ozzie dat wil.
Ook kun je beter een pointer (current, next) gebruiken voor de iteratie dan een tellertje. De pointer is niet afhankelijk van de key (text, int, etc.), terwijl een tellertje dat wel is. en voor de puristen is een tellertje ook plainfout, aangezien keys in PHP alleen maar strings zijn, omdat alle arrays in PHP hashtables zijn)
Als laatste snap ik niet waarom je niet "gewoon een foreach loop" gebruikt? Gebruik features waarvoor ze gemaakt zijn en ga dan niet met andere dingen stoeien. Overigens zijn in dit topic de while loop oplossingen en de foreach oplossing gegeven door Ozzie compleet anders.
En eigenlijk klopt dat ook niet helemaal, omdat je bij een hashtable niet zelf de volgorde van de elementen kunt bepalen. Bij PHP kan dat wel, omdat er een chained/linked hashtable gebruikt wordt. > omdat alle arrays in PHP hashtables zijn
Tot zover kan ik je prima volgen...
>> Het gevolg hiervan is dat wanneer je een array afloopt met while($array[$i]){$i++;} de tijd die je while-loop nodig heeft kwadratisch (!) toeneemt met het aantal elementen in je array. Een foreach-loop heeft in dit geval een lineair verband.
Say whhhhaaaat?? :-)
Bedoel je dat die $i telkens "gezocht" moet worden, terwijl in de for-each gewoon naar het volgende element wordt gesprongen?
>> Om de while loop goed te kunnen gebruiken zou er dus een break in de else statement moeten. Ik weet niet of Ozzie dat wil.
Ja, het is of een while-loop, of een foreach met een break in de else. Beiden komt op hetzelfde neer. Dus in dat geval kan ik beter de snellere foreach variant gebruiken.
>> Als laatste snap ik niet waarom je niet "gewoon een foreach loop" gebruikt? Gebruik features waarvoor ze gemaakt zijn en ga dan niet met andere dingen stoeien.
Dat zal ik je uitleggen Wouter. Ik dacht namelijk dat een while juist bedoeld was om iets te doen "zolang een bepaalde expressie geldig is". Dus ik dacht "zolang die color geset is", doe iets... Ik dacht dat dat dan juist wel een goede reden zou zijn om while te gebruiken. Maar heb ik dat dan verkeerd begrepen?
Toevoeging op 26/06/2014 21:09:31:
EXTRA OPMERKING
Ik heb even een benchmark gedaan, en wat blijkt... de while-loop is toch ietsje (niet veel) sneller. Ik denk dat het komt omdat de betreffende array een numerieke array is waarbij de getallen in de juiste volgorde staan. Dus hij beging met key 0 en loopt dan op naar boven. Zou dat de reden zijn waarom de while-loop toch sneller gaat? >> Zo zoekt hij net zolang tot hij de juiste key gevonden heeft.
Ja, dat bedoelde ik. Wat overigens niet waar blijkt te zijn. ;-) Ik had ergens in mijn achterhoofd zitten dat arrays geïmplementeerd zijn als linked lists, maar het zijn dus ordered hashtables. Dat is stukken beter, maar nog wel steeds een klein beetje langzamer dan echte arrays (maar het geeft wel wat meer flexibiliteit, omdat je ook niet-numerieke keys kunt gebruiken).
> Ja, het is of een while-loop, of een foreach met een break in de else.
Geen else nodig:
> Ik dacht namelijk dat een while juist bedoeld was om iets te doen "zolang een bepaalde expressie geldig is".
Dat klopt. Maar in jouw geval heb je steeds een andere expressie: de eerste keer $foo[0]['color'], daarna $foo[1]['color'], etc. Daardoor moet je in je while-loop dus wat extra logica inbouwen om door je array heen te itereren, waardoor een foreach al snel een beter mechanisme is om je doel te bereiken.
> Ik heb even een benchmark gedaan, en wat blijkt... de while-loop is toch ietsje (niet veel) sneller.
Uiteraard heb ik dat ook meteen maar even getest ;-) en bij mij is de while consequent zo'n 25% langzamer. Zou het kunnen dat je in je while geen "$val = $foo[$i]" hebt gedaan? In dat geval is je while-loop namelijk wel sneller, maar functioneel niet gelijk aan de foreach.
En om mijn uitspraak uit mijn eerdere post meteen te ontkrachten: de tijdsduur van de while neemt (gelukkig) niet kwadratisch toe met het aantal elementen. Overigens heeft PHP enkele array-functies waarbij dat wel het geval is (in_array() bijvoorbeeld).
> Ik denk dat het komt omdat de betreffende array een numerieke array is waarbij de getallen in de juiste volgorde staan. Dus hij begint met key 0 en loopt dan op naar boven. Zou dat de reden zijn waarom de while-loop toch sneller gaat?
Nee. Ik heb het ook met een niet-geordende array geprobeerd en dat maakt geen verschil. Even voor de volledigheid: het feit dat (in PHP) een array numerieke keys heeft, wil niet zeggen dat de elementen in numerieke volgorde staan. Ze staan altijd in de volgorde waarin je ze aan de array hebt toegevoegd:
In elke andere taal -die ik ken- zou dat lijstje 0/1/2 als volgorde hebben gehad. > Bedoel je dat die $i telkens "gezocht" moet worden, terwijl in de for-each gewoon naar het volgende element wordt gesprongen?
Dat zou ook inderdaad kunnen.
>> Uiteraard heb ik dat ook meteen maar even getest ;-) en bij mij is de while consequent zo'n 25% langzamer.
>> Zou het kunnen dat je in je while geen "$val = $foo[$i]" hebt gedaan?
Wat bedoel je hiermee?
Ik doe (ongeveer) dit:
En dat is sneller dan:
De while-loop wint het van de foreach-loop bij mij. >> Geen else nodig: Je zit appels met pannekoeken te vergelijken. Waar komt die $i in de foreach ineens vandaan? Waarschijnlijk nog uit de while-loop, en die staat daar dus op de waarde van de hoogste key. Geen wonder dat de foreach langzamer is.
(grr... je code aanpassen terwijl ik een reactie zit te schrijven... het zou verboden moeten worden! ;-) )
Maar eigenlijk bedoelde ik dit:
De foreach kent namelijk de waarde van $foo[$i] toe aan $value. Als je dat in je while-loop niet doet, is hij dus functioneel niet hetzelfde en test je ook twee verschillende dingen.
Lol... die had ik verkeerd gekopieerd, maar je had m'n edit waars. nog niet gezien :)
In de while gebruik ik gewoon direct $foo[$i]['color'] ipv $foo eerst aan een value toe te kennen. >> Je zit appels met pannekoeken te vergelijken. Waar komt die $i in de foreach ineens vandaan? Waarschijnlijk nog uit de while-loop, en die staat daar dus op de waarde van de hoogste key. Geen wonder dat de foreach langzamer is.
Oftewel de plusjes voor de variabelen worden eerst uitgevoerd voor het echoen.
Gewijzigd op 25/06/2014 14:54:04 door gerhard l
Ah zo, thanks. En bij het ophogen van een iterator, zoals in het voorbeeld van Erwin, wat is dan het voordeel van ++$i versus $i++ ? Of maakt het in dat geval niks uit?
deze test, is ++$i sneller/minder geheugen als $i++ als het alleen voor ophogen dient.
Ik denk niet dat het veel uitmaakt, maar volgens Dankjewel gerhard. Ik heb even een benchmark gedaan en de ++$i variant is inderdaad wat sneller!
Over snelheid gesproken: aangezien PHP feitelijk gezien geen arrays kent, is foreach($array) aanmerkelijk sneller dan while($array[$i]). Dat kun je niet compenseren met je ++$i. ;-)
Wat bedoel je daarmee Willem?
Stel je hebt een array van 10 integers en een integer is 4 bytes. Om het eerste element $array[0] te vinden neem je dan het beginadres van de datastructuur en telt er 0x4 bytes bij op. Het zevende element is dus te vinden op 6x4 bytes vanaf het begin.
In PHP is een array eigenlijk een linked list. Als je een element toevoegt aan de array, zal in het laatste element een pointer worden opgenomen naar het nieuwe element. Als je $array[3] wilt hebben, begint PHP te zoeken bij het eerste element van de array. Hij vergelijkt de array key met de key die jij zoekt, en als die niet overeenkomen, gaat hij via de pointer naar het volgende element. Zo zoekt hij net zolang tot hij de juiste key gevonden heeft.
Het gevolg hiervan is dat wanneer je een array afloopt met while($array[$i]){$i++;} de tijd die je while-loop nodig heeft kwadratisch (!) toeneemt met het aantal elementen in je array. Een foreach-loop heeft in dit geval een lineair verband.
While *stopt* wanneer er geen element meer met color is, foreach zou hem gewoon *overslaan*. Om de while loop goed te kunnen gebruiken zou er dus een break in de else statement moeten. Ik weet niet of Ozzie dat wil.
Ook kun je beter een pointer (current, next) gebruiken voor de iteratie dan een tellertje. De pointer is niet afhankelijk van de key (text, int, etc.), terwijl een tellertje dat wel is. en voor de puristen is een tellertje ook plainfout, aangezien keys in PHP alleen maar strings zijn, omdat alle arrays in PHP hashtables zijn)
Als laatste snap ik niet waarom je niet "gewoon een foreach loop" gebruikt? Gebruik features waarvoor ze gemaakt zijn en ga dan niet met andere dingen stoeien.
Gewijzigd op 26/06/2014 18:25:24 door Wouter J
En eigenlijk klopt dat ook niet helemaal, omdat je bij een hashtable niet zelf de volgorde van de elementen kunt bepalen. Bij PHP kan dat wel, omdat er een chained/linked hashtable gebruikt wordt.
Tot zover kan ik je prima volgen...
>> Het gevolg hiervan is dat wanneer je een array afloopt met while($array[$i]){$i++;} de tijd die je while-loop nodig heeft kwadratisch (!) toeneemt met het aantal elementen in je array. Een foreach-loop heeft in dit geval een lineair verband.
Say whhhhaaaat?? :-)
Bedoel je dat die $i telkens "gezocht" moet worden, terwijl in de for-each gewoon naar het volgende element wordt gesprongen?
>> Om de while loop goed te kunnen gebruiken zou er dus een break in de else statement moeten. Ik weet niet of Ozzie dat wil.
Ja, het is of een while-loop, of een foreach met een break in de else. Beiden komt op hetzelfde neer. Dus in dat geval kan ik beter de snellere foreach variant gebruiken.
>> Als laatste snap ik niet waarom je niet "gewoon een foreach loop" gebruikt? Gebruik features waarvoor ze gemaakt zijn en ga dan niet met andere dingen stoeien.
Dat zal ik je uitleggen Wouter. Ik dacht namelijk dat een while juist bedoeld was om iets te doen "zolang een bepaalde expressie geldig is". Dus ik dacht "zolang die color geset is", doe iets... Ik dacht dat dat dan juist wel een goede reden zou zijn om while te gebruiken. Maar heb ik dat dan verkeerd begrepen?
Toevoeging op 26/06/2014 21:09:31:
EXTRA OPMERKING
Ik heb even een benchmark gedaan, en wat blijkt... de while-loop is toch ietsje (niet veel) sneller. Ik denk dat het komt omdat de betreffende array een numerieke array is waarbij de getallen in de juiste volgorde staan. Dus hij beging met key 0 en loopt dan op naar boven. Zou dat de reden zijn waarom de while-loop toch sneller gaat?
Gewijzigd op 26/06/2014 20:47:25 door Ozzie PHP
Ja, dat bedoelde ik. Wat overigens niet waar blijkt te zijn. ;-) Ik had ergens in mijn achterhoofd zitten dat arrays geïmplementeerd zijn als linked lists, maar het zijn dus ordered hashtables. Dat is stukken beter, maar nog wel steeds een klein beetje langzamer dan echte arrays (maar het geeft wel wat meer flexibiliteit, omdat je ook niet-numerieke keys kunt gebruiken).
> Ja, het is of een while-loop, of een foreach met een break in de else.
Geen else nodig:
Code (php)
> Ik dacht namelijk dat een while juist bedoeld was om iets te doen "zolang een bepaalde expressie geldig is".
Dat klopt. Maar in jouw geval heb je steeds een andere expressie: de eerste keer $foo[0]['color'], daarna $foo[1]['color'], etc. Daardoor moet je in je while-loop dus wat extra logica inbouwen om door je array heen te itereren, waardoor een foreach al snel een beter mechanisme is om je doel te bereiken.
> Ik heb even een benchmark gedaan, en wat blijkt... de while-loop is toch ietsje (niet veel) sneller.
Uiteraard heb ik dat ook meteen maar even getest ;-) en bij mij is de while consequent zo'n 25% langzamer. Zou het kunnen dat je in je while geen "$val = $foo[$i]" hebt gedaan? In dat geval is je while-loop namelijk wel sneller, maar functioneel niet gelijk aan de foreach.
En om mijn uitspraak uit mijn eerdere post meteen te ontkrachten: de tijdsduur van de while neemt (gelukkig) niet kwadratisch toe met het aantal elementen. Overigens heeft PHP enkele array-functies waarbij dat wel het geval is (in_array() bijvoorbeeld).
> Ik denk dat het komt omdat de betreffende array een numerieke array is waarbij de getallen in de juiste volgorde staan. Dus hij begint met key 0 en loopt dan op naar boven. Zou dat de reden zijn waarom de while-loop toch sneller gaat?
Nee. Ik heb het ook met een niet-geordende array geprobeerd en dat maakt geen verschil. Even voor de volledigheid: het feit dat (in PHP) een array numerieke keys heeft, wil niet zeggen dat de elementen in numerieke volgorde staan. Ze staan altijd in de volgorde waarin je ze aan de array hebt toegevoegd:
Code (php)
In elke andere taal -die ik ken- zou dat lijstje 0/1/2 als volgorde hebben gehad.
Gewijzigd op 27/06/2014 00:35:39 door Willem vp
Dat zou ook inderdaad kunnen.
>> Uiteraard heb ik dat ook meteen maar even getest ;-) en bij mij is de while consequent zo'n 25% langzamer.
>> Zou het kunnen dat je in je while geen "$val = $foo[$i]" hebt gedaan?
Wat bedoel je hiermee?
Ik doe (ongeveer) dit:
Code (php)
En dat is sneller dan:
Code (php)
De while-loop wint het van de foreach-loop bij mij.
Gewijzigd op 27/06/2014 00:36:05 door Ozzie PHP
(grr... je code aanpassen terwijl ik een reactie zit te schrijven... het zou verboden moeten worden! ;-) )
Maar eigenlijk bedoelde ik dit:
Code (php)
De foreach kent namelijk de waarde van $foo[$i] toe aan $value. Als je dat in je while-loop niet doet, is hij dus functioneel niet hetzelfde en test je ook twee verschillende dingen.
Gewijzigd op 27/06/2014 00:46:26 door Willem vp
Lol... die had ik verkeerd gekopieerd, maar je had m'n edit waars. nog niet gezien :)
In de while gebruik ik gewoon direct $foo[$i]['color'] ipv $foo eerst aan een value toe te kennen.
Gewijzigd op 27/06/2014 00:46:07 door Ozzie PHP