Door
Peter Sanders
op 23-11-2011 10:11
gewijzigd op 23-11-2011 10:12
1.936 views
Hallo,
Ik ben al wel een tijd bezig met php, maar heb nooit echt iets met arrays gedaan. Nu wil ik wat wiskunde gaan doen met php en een soort van voorwaardes in een foreach-lus zetten die vergelijkbaar zijn met een WHERE-clausule uit een sql-query.
Ik zet om te beginnen een veld uit een databank in een array. Vervolgens draai ik daar een foreach-lus overheen waarin ik alle data die niet aan mijn voorwaardes voldoen weer uit het array haal. Uiteindelijk print ik het array weer om te kijken wat er in zit.
$SlotArray = array();
$sql = "SELECT * FROM aex";
$exec_sql = mysql_query($sql) or die("Foutmelding: ".mysql_error());
while($z = mysql_fetch_assoc($exec_sql)){
$SlotArray[$z['Datum']] = $z['Slot'];
}
reset($SlotArray);
foreach($SlotArray as $waarde){
if($waarde > 300 OR $waarde < 290){
unset($SlotArray[key($SlotArray)]);
}
}
print_r($SlotArray);
De eerste 10 resultaten van het array zijn echter de volgende:
Er zit dus ergens iets fout. Ik begrijp echter absoluut niet waar. Heeft iemand enig idee waar ik fout zit?
ps. Ik weet dat ik natuurlijk ook gewoon een "WHERE Slot < 300 AND Slot > 290" kan toevoegen aan de sql-query. In een later stadium in mijn berekeningen zal dat echter niet meer kunnen. Bovendien wil ik ook gewoon wat meer leren werken met arrays.. :-)
Wat er precies mis gaat kan ik ook niet achterkomen, maar het zit in elk geval in het gebruik van "$SlotArray[key($SlotArray)]" Als je het iets anders schrijft krijg je het wel goed:
foreach($SlotArray as $k => $waarde){
if($waarde > 300 OR $waarde < 290){
unset($SlotArray[$k]);
}
}
Op deze manier haal je dus zowel de waarde van het huidige element op (in $waarde), als de key (in $k).
Dank! Die oplossing werkt inderdaad perfect. Handig inderdaad dat ik dan gewoon de key en de waarde allebei apart in een variabele heb. Zoals gezegd, ik begin net met arrays, dus ik moet het concept nog een beetje in mijn hoofd krijgen.
Nog een ander vraagje. Als ik nou een twee-dimensionaal array heb. Hoe zet ik dan de beide keys in een variabele?
Dus ik heb bijvoorbeeld een twee-dimensionaal array waarin één key de datum is, en één key de tijd. De inhoud van het array is de koers van de aex op dat tijdstip.
Dus zoiets:
$koers['1996-12-27']['16:35:00'] = 290.01;
$koers['1996-12-27']['16:36:00'] = 290.46;
Hoe zou ik dit nu inladen in een foreach-lus? Ik heb het volgende geprobeerd.
foreach($koers as $datum => $tijd => $waarde){
echo "op ".$datum." om ".$tijd." was de koers van de aex ".$waarde;
}
Daarop krijg ik echter een foutmelding: Parse error: syntax error, unexpected T_DOUBLE_ARROW, expecting ')'
<?php
foreach($koers as $datum => $value)
{
foreach($value as tijd => $waarde)
{
echo "op ".$datum." om ".$tijd." was de koers van de aex ".$waarde;
}
}
?>
Dubbele foreach loop. De waarde die je uit de eerste loop krijgt is weer een array, dus die kan je op dezelfde manier aanpakken als de eerste:
<?php
foreach($koers as $datum => $waarde1){
foreach( $waarde1 as $tijd => $waarde2){
echo "op ".$datum." om ".$tijd." was de koers van de aex ".$waarde2;
}
}
?>
Ah, met een dubbele foreach dus. Ok! Dat heb ik ook weer geleerd!
Als ik zo vrij mag zijn om nog twee vraagjes te stellen (ik leer zo lekker veel hier);
1) Is het mogelijk om met dat laatste array alle resultaten uit 2004 te verwijderen? Dus iets in de trant van
<?php
foreach($koers as $datum => $value)
{
foreach($value as tijd => $waarde)
{
if($datum == '2004%'){
unset($koers[$datum][$tijd]);
}
}
}
?>
Ik begrijp alleen niet hoe je een wildcard doet zoals je dat in sql met een % doet. Jullie (of iemand anders) toevallig enig idee?
Vraag 2) Is het mogelijk om met de resultaten uit een array, de resultaten uit een ander array op te halen? Zo heb ik twee arrays:
$aex['1996-12-27']['16:35:00'] = 290.01;
$aex['1996-12-27']['16:36:00'] = 290.46;
etc.
en
$dowjones['1996-12-27']['16:35:00'] = 2090;
$dowjones['1996-12-27']['16:36:00'] = 2095;
Nu wil ik alle elementen uit het $aex-array unsetten waarvan de datum niet voorkomt in het $dowjones-array. Dus zoiets als dit:
<?php
foreach($aex as $aex_datum => $value)
{
foreach($dowjones as $dowjones_datum => $waarde)
{
if($dowjones_datum != $aex_datum)
{
unset($aex[$aex_datum]);
}
}
}
?>
Maar dat zou volgens mij alles unsetten, aangezien er voor elke $aex_datum wel een $dowjones_datum is die er niet aan gelijk is. Enig idee hoe ik dit zou kunnen oplossen?
Vraag 1: die zou ik oplossen met een substr dus:
if( substr($datum,0,4) == '2004' )
Moet je wel alle elementen door. Ik ken geen simpelere oplossing (wat niet betekent dat die er niet is natuurlijk).
Vraag 2: Op die manier is het heel er langzaam ( O(n*m) )en waarschijnlijk wordt alles eruitgehaald.
Wat je wel kan, met de functie isset() is checken of key "aex_datum" bestaat in de array $dowjones. Dus:
Nu weet ik alleen niet hoe isset precies door de array heen gaat en daarmee of het enigszins snel is. Misschien is het van dezelfde orde.
Als je de arrays gesorteerd op datum krijgt (bijvoorbeeld uit de database) dan kan het wel veel sneller ( O(n+m) ). Begin bij beide arrays bij het eerste element, check of ze gelijk zijn. Zo nee, controleer of de aex_datum lager is dan de dowjones datum. Zo ja, verwijder de aex waarde en ga in die array naar de volgende. Zo nee, ga in de dowjones array naar de volgende. Zijn beide data wel gelijk, ga in beide arrays naar de volgende waarde. Ga zo door tot je het laatste element heb gehad in de aex array
In pseudo code:
reset(aex_array);
reset(dowjones_array);
while ( !end of array(aex_array) ){
if (aex_array[datum] == dowjones[datum]){
go to next element in aex_array, go to next element in dowjones_array
} else {
if (aex_array[datum] < dowjones[datum]){
unset(aex_array[datum])
go to next element in aex_array
} else {
go to next element in dowjones_array
}
}
}
1) Is het mogelijk om met dat laatste array alle resultaten uit 2004 te verwijderen? Dus iets in de trant van
<?php
foreach($koers as $datum => $value)
{
foreach($value as tijd => $waarde)
{
if($datum == '2004%'){
} unset($koers[$datum][$tijd]);
}
}
}
?>
Om alles uit 2004 te verwijderen heb je maar één loop nodig omdat je dan de datum al weet.
Vraag 2) Is het mogelijk om met de resultaten uit een array, de resultaten uit een ander array op te halen? Zo heb ik twee arrays:
$aex['1996-12-27']['16:35:00'] = 290.01;
$aex['1996-12-27']['16:36:00'] = 290.46;
etc.
en
$dowjones['1996-12-27']['16:35:00'] = 2090;
$dowjones['1996-12-27']['16:36:00'] = 2095;
Nu wil ik alle elementen uit het $aex-array unsetten waarvan de datum niet voorkomt in het $dowjones-array. Dus zoiets als dit:
<?php
foreach($aex as $aex_datum => $value)
{
foreach($dowjones as $dowjones_datum => $waarde)
{
if($dowjones_datum != $aex_datum)
{
unset($aex[$aex_datum]);
}
}
}
?>
Maar dat zou volgens mij alles unsetten, aangezien er voor elke $aex_datum wel een $dowjones_datum is die er niet aan gelijk is. Enig idee hoe ik dit zou kunnen oplossen?
Je kijkt of de datum een key is in het andere array().
Zo niet, verwijderen.
Over vraag 1) Okee, dankjewel. Daarmee zal het wel lukken denk ik.
Over vraag 2) Het zal uiteindelijk om een redelijk groot array gaan (ongeveer 3,6 miljoen waardes) waar ik mbv een paar (zelfgeschreven) functies een aantal berekeningen op wil doen. Die berekeningen zal ik ook nog ongeveer een miljoen keer moeten loopen, dus het zal al met al wel eventjes duren. Ik denk echter dat dit sneller zal gaan dan met sql aangezien ik zo alles in het geheugen heb staan en het daardoor naar mijn weten vooral zwaar is voor de CPU.
Ik zal in ieder geval eens wat tests doen met isset, en kijken hoe lang dat duurt. Als dat erg lang is dan zal ik het proberen met het tweede idee wat je voorsteld (wat ik overigens redelijk briljant vind).