[PHP] Door array loopen

Pagina: 1
Acties:

Onderwerpen


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Ik heb de volgende array:
PHP:
1
2
3
4
5
6
$arr['a'] = array('dit' => 10, 'dat' => 20);
$arr['b'] = array('dit' => 15, 'dat' => 30);
$arr['c'] = array('dit' => 13, 'dat' => 50);
$arr['d'] = array('dit' => 17, 'dat' => 10);
$arr['e'] = array('dit' => 23, 'dat' => 42);
$arr['f'] = array('dit' => 57, 'dat' => 17);


De werkelijke array is veel langer. Ik wil door deze array loopen, zodat telkens 2 opvolgende elementen geprint worden:
HTML:
1
2
3
a: 10 / 20 en b: 15 / 30<br>
c: 13 / 50 en d: 17 / 10<br>
e: 23 / 42 en f: 57 / 17<br>

Normaal loop ik als volgt door een array:
PHP:
1
2
3
foreach ($arr as $index => $data) {
  $index .': '. $data['dit'] .' / '. $data['dat']. '<br>';
}

Maar dan komt "b" op een aparte regel te staan:
HTML:
1
2
3
4
5
6
a: 10 / 20<br> 
b: 15 / 30<br>
c: 13 / 50<br> 
b: 17 / 10<br>
e: 23 / 42<br> 
f: 57 / 17<br>

Hoe kan ik de loop aanpassen, zodat ik ook al beschikking heb over de data van de volgende regel uit de array?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

Verwijderd

gebruik maken van keys :? Beetje basic...

edit
Of je houdt een tellertje bij, door check van even/oneven getal bepaal je of je een <br> afdrukt. Beetje creatief zijn he :>

[ Voor 61% gewijzigd door Verwijderd op 09-03-2008 19:52 ]


Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Geen foreach gebruiken maar een for() zodat je gewoon individuele array elementen kunt benaderen aan de hand van de index. Zie AtleX in "[PHP] Door array loopen" :)

[ Voor 24% gewijzigd door AtleX op 09-03-2008 20:04 ]

Sole survivor of the Chicxulub asteroid impact.


Acties:
  • 0 Henk 'm!

  • Onbekend
  • Registratie: Juni 2005
  • Laatst online: 22-09 09:45

Onbekend

...

Waarom gebruik je niet gewoon een for-lus?

En in de for-lus zet je bijvoorbeeld het volgende:
if ( $Counter % 2 == 1 )
printf "<br>"

Een beetje basic allemaal....

[ Voor 11% gewijzigd door Onbekend op 09-03-2008 19:54 ]

Speel ook Balls Connect en Repeat


Acties:
  • 0 Henk 'm!

  • Ramon
  • Registratie: Juli 2000
  • Nu online

Check mijn V&A ads: https://tweakers.net/aanbod/user/9258/


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Wat is d'r mis met iets als:

PHP:
1
2
3
4
5
6
7
for ($i = 0; $i < count($arr); $i = $i + 2)
{

  doe_iets($arr[$i]);
  doe_iets($arr[$i + 1]);

}

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Negeer mijn eerste post maar:

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
<?php
error_reporting(E_ALL);

$arr['a'] = array('dit' => 10, 'dat' => 20);
$arr['b'] = array('dit' => 15, 'dat' => 30);
$arr['c'] = array('dit' => 13, 'dat' => 50);
$arr['d'] = array('dit' => 17, 'dat' => 10);
$arr['e'] = array('dit' => 23, 'dat' => 42);
$arr['f'] = array('dit' => 57, 'dat' => 17); 

$i = 0;
foreach ($arr as $index => $data) 
{
    echo $index.": ".$data["dit"]." / ".$data["dat"]." ";
    
    $i++;
    if ($i % 2 == 0)
        echo "<br>";
}
?>


Iedereen (mijzelf meegerekend) vergeet hier even dat hij de keys ook wil hebben. En door deze array kan je niet eens heen loopen met een for() omdat hij niet indexed is.
Osiris schreef op zondag 09 maart 2008 @ 20:00:
Wat is d'r mis met iets als:

PHP:
1
//code
Het feit dat je count() bij elke iteratie aanroept?

[ Voor 27% gewijzigd door AtleX op 09-03-2008 20:04 ]

Sole survivor of the Chicxulub asteroid impact.


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
AtleX schreef op zondag 09 maart 2008 @ 20:00:
[...]

Het feit dat je count() bij elke iteratie aanroept?
Nah, da's niet eens 't meest erge, die $arr werkt niet met cijfertjes, maar met letters, dus $i gaat niet werken _O- En count tig keer aanroepen is meer performance, goed punt, maar daar doelde ik niet echt op :+

Acties:
  • 0 Henk 'm!

  • AtleX
  • Registratie: Maart 2003
  • Niet online

AtleX

Tyrannosaurus Lex 🦖

Ja, maar dat had ik boven de quote van jouw post al gezegd. ;)

Sole survivor of the Chicxulub asteroid impact.


Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
AtleX schreef op zondag 09 maart 2008 @ 20:00:
PHP:
1
2
3
4
5
6
7
8
9
$i = 0;
foreach ($arr as $index => $data) 
{
    echo $index.": ".$data["dit"]." / ".$data["dat"]." ";
    
    $i++;
    if ($i % 2 == 0)
        echo "<br>";
}
Bedankt voor je antwoord, maar hiermee is mijn probleem nog niet weg. Dat ligt aan mij: ik heb het probleem teveel vereenvoudigd. In werkelijkheid moet ik de volgende output genereren:
PHP:
1
2
3
$new_arr[0] = array('a', '10', '20', 'b', '15', '30');
$new_arr[1] = array('c', '13', '50', 'd', '17', '10');
$new_arr[2] = array('e', '23', '42', 'f', '57', '17');

Dat is dus lastiger dan het vormen van een string. Ik heb nu dit:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$arr['a'] = array('dit' => 10, 'dat' => 20);
$arr['b'] = array('dit' => 15, 'dat' => 30);
$arr['c'] = array('dit' => 13, 'dat' => 50);
$arr['d'] = array('dit' => 17, 'dat' => 10);
$arr['e'] = array('dit' => 23, 'dat' => 42);
$arr['f'] = array('dit' => 57, 'dat' => 17); 

$i = 0;
foreach ($arr as $index => $data) {
  $new_arr[$i] = array($index, $data['dit'], $data['dat']);
  $i++;
  if ($i % 2 == 0) {
    array_push($new_arr[$i - 1], $index, $data['dit'], $data['dat']);
  }
}

print_r($new_arr);

Maar dan krijg ik een heel raar resultaat. Wie kan mij verder helpen?

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

Verwijderd

TS, het is me niet helemaal duidelijk van welke array je naar welke output toe moet? Misschien heb je voorbeeldje van de output zoals je die moet hebben?

Acties:
  • 0 Henk 'm!

  • Reveller
  • Registratie: Augustus 2002
  • Laatst online: 05-12-2022
Verwijderd schreef op zondag 09 maart 2008 @ 20:41:
TS, het is me niet helemaal duidelijk van welke array je naar welke output toe moet? Misschien heb je voorbeeldje van de output zoals je die moet hebben?
Natuurlijk :) Dit is de input array:
PHP:
1
2
3
4
5
6
$arr['a'] = array('dit' => 10, 'dat' => 20);
$arr['b'] = array('dit' => 15, 'dat' => 30);
$arr['c'] = array('dit' => 13, 'dat' => 50);
$arr['d'] = array('dit' => 17, 'dat' => 10);
$arr['e'] = array('dit' => 23, 'dat' => 42);
$arr['f'] = array('dit' => 57, 'dat' => 17);

Ik ben op zoek naar een loop die $arr omzet naar de volgende output array:
PHP:
1
2
3
$new_arr[0] = array('a', '10', '20', 'b', '15', '30');
$new_arr[1] = array('c', '13', '50', 'd', '17', '10');
$new_arr[2] = array('e', '23', '42', 'f', '57', '17');

De array $new_arr gebruik ik vervolgens als input voor een functie die er een html tabel van maakt:
HTML:
1
2
3
4
5
6
7
8
9
10
11
<table>
  <tr>
    <td>a</td><td>10</td><td>20</td><td>b</td><td>15</td><td>30</td>
  </tr>
  <tr>
    <td>c</td><td>13</td><td>50</td><td>d</td><td>17</td><td>10</td>
  </tr>
  <tr>
    <td>e</td><td>23</td><td>42</td><td>f</td><td>57</td><td>17</td>
  </tr>
</table>

Ik hoop dat het nu duidelijk is :)

"Real software engineers work from 9 to 5, because that is the way the job is described in the formal spec. Working late would feel like using an undocumented external procedure."


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Ik zou dan misschien toch iets doen met de array-functie(s) die Ramon aanhaalt:

Dit stukje code levert geloof ik het resultaat wat je wil, maar 't is wel vrij ranzig opgezet met heerlijk onduidelijke variabel-naampjes enzo :X

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
$arr     = array();
$new_arr = array();

$arr['a'] = array('dit' => 10, 'dat' => 20);
$arr['b'] = array('dit' => 15, 'dat' => 30);
$arr['c'] = array('dit' => 13, 'dat' => 50);
$arr['d'] = array('dit' => 17, 'dat' => 10);
$arr['e'] = array('dit' => 23, 'dat' => 42);
$arr['f'] = array('dit' => 57, 'dat' => 17);

$total = count($arr);

for($i = 0; $i < ($total/2); $i++)
{

  $new_arr[$i] = array();

  for($tmp = 0; $tmp < 2; $tmp++)
  {

    $temp_array = each($arr);

    array_push($new_arr[$i], $temp_array[0]);
    foreach($temp_array[1] as $value)
    {

      array_push($new_arr[$i], $value);

    }

  }

}

print_r($new_arr);


En dat for-loopje om iets simpelweg tweemaal uit te voeren moet vast ook wel simpeler kunnen 8)7

Een foreachje overigens voor als de TS z'n ditjes en datjes uit wil breiden, dan gaat dat meteen goed. :)

Ik ging overigens gemakshalve er vanuit dat je $arr altijd een even aantal entries heeft. Geen idee of die for-loop floating points slikt, maar iets zegt me dat als je een extra key aan $arr toevoegt (dus een oneven aantal krijgt) hij die laatste niet meeneemt. Hm, toch wel, al gaat er dan wel iets (obviously) mis met de for-loop die tweemaal each() aanroept, want hij zit bij de tweede each() al bij 't end van z'n array, dus krijg je een lege entry in $new_arr[$i].

[ Voor 22% gewijzigd door Osiris op 09-03-2008 20:59 ]


Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$tmp = null;
$res = array();
foreach ($arr as $idx => $val) {
  if (!is_null($tmp)) {
    $res[] = array($idx=>$val) + $tmp;
    $tmp = null;
  }
  else {
    $tmp = array($idx=>$val);
  }
}

Zoiets?

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Spockz schreef op zondag 09 maart 2008 @ 20:56:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
<?php
$tmp = null;
$res = array();
foreach ($arr as $idx => $val) {
  if (!is_null($tmp)) {
    $res[] = array($idx=>$val) + $tmp;
    $tmp = null;
  }
  else {
    $tmp = array($idx=>$val);
  }
}

Zoiets?
Dan krijg ik als output in $res:

Array
(
    [0] => Array
        (
            [b] => Array
                (
                    [dit] => 15
                    [dat] => 30
                )

            [a] => Array
                (
                    [dit] => 10
                    [dat] => 20
                )

        )

)

et c…

Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
PHP:
1
2
3
4
5
6
7
$i = 0;
$new_arr = array();
foreach($arr as $key => $val) {
    $i++;
    if($i % 2 == 0) $new_arr[] = array_merge($tmp, array($key, $val['dit'], $val['dat']) );
    else               $tmp = array($key, $val['dit'], $val['dat']);
}

Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Hey, die geeft ook de goeie output, wie gaat benchmarken? :+

Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

@Osiris. Ok, je moet er van maken.
PHP:
1
$res[] = $tmp + array($idx => $val);


En dan nog nog al die dingen (in $res) platslaan natuurlijk.

[ Voor 3% gewijzigd door Spockz op 09-03-2008 21:19 ]

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

Osiris schreef op zondag 09 maart 2008 @ 21:15:
Hey, die geeft ook de goeie output, wie gaat benchmarken? :+
10.000x uitvoeren:
GlowMouse: 0.16371178627014
Osiris: 0.27994799613953

[ Voor 5% gewijzigd door Spockz op 09-03-2008 21:24 ]

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • Osiris
  • Registratie: Januari 2000
  • Niet online
Spockz schreef op zondag 09 maart 2008 @ 21:23:
[...]

10.000x uitvoeren:
GlowMouse: 0.16371178627014
Osiris: 0.27994799613953
:+ Ik wist het :D

Dat ik een prutser ben dan hè, lager = beter, I know :+

[ Voor 13% gewijzigd door Osiris op 09-03-2008 21:28 ]


Acties:
  • 0 Henk 'm!

  • Sjoerd
  • Registratie: December 2003
  • Niet online
Spockz schreef op zondag 09 maart 2008 @ 21:23:
[...]

10.000x uitvoeren:
GlowMouse: 0.16371178627014
Osiris: 0.27994799613953
compleet offtopic, hoe meet je zoiets eigenlijk? :)

Modelbouw - Alles over modelbouw, van RC tot diorama


Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

@Osiris, Ik zit er tussen in:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
function spockz ($arr) {
  $tmp = null;
  $res = array();
  foreach ($arr as $idx => $val) {
    if (!is_null($tmp)) {
      $res[] = array_merge($tmp, array_merge(array($idx), array_values($val)));
      $tmp = null;
    }
    else {
      $tmp = array_merge(array($idx), array_values($val));
    }
  }
}

code:
1
2
3
GlowMouse: 0.15922999382019
Osiris:    0.28305315971375
Spockz:    0.2485089302063


@Sjoerd, Testing code:
PHP:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
$start = -1*microtime(true);
for ($i=0; $i<10000; $i++) {
  glowmouse($arr);
}
echo 'GlowMouse: '.(microtime(true)+$start).'<br>';

$start = -1*microtime(true);
for ($i=0; $i<10000; $i++) {
  osiris($arr);
}
echo 'Osiris: '.(microtime(true)+$start).'<br>';

$start = -1*microtime(true);
for ($i=0; $i<10000; $i++) {
  spockz($arr);
}
echo 'Spockz: '.(microtime(true)+$start).'<br>';

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Wil je nog meer performance dan sla je de else van mij niet op in een array, maar in losse variabelen. Dat scheelt weer een array_merge, en maakt het ongeveer 50% sneller. Maar bij deze obscure code die toch geen bottleneck vormt, hecht ik meer waarde aan leesbaarheid.

Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

Glowmouse, ik heb jouw code nog ietsjes versneld door geen modulo te gebruiken maar een bitwise check.

PHP:
1
2
3
4
5
6
7
8
9
function glowmouse ($arr) {
  $i = 1;
  $new_arr = array();
  foreach($arr as $key => $val) {
      $i++;
      if(($i&1) == 1)    $new_arr[] = array_merge($tmp, array($key, $val['dit'], $val['dat']) );
      else               $tmp = array($key, $val['dit'], $val['dat']);
  } 
}

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Spockz schreef op zondag 09 maart 2008 @ 22:06:
Glowmouse, ik heb jouw code nog ietsjes versneld door geen modulo te gebruiken maar een bitwise check.
Dat is weer gerommel in de marges die de code er nauwelijks sneller maar wel onleesbaarder op maakt. In principe heb je helemaal geen integer nodig, één bit is genoeg om aan te geven in welke rij je zit. Ga je alleen voor performance, dan krijg je waarschijnlijk zoiets (de foreach door een for of een while vervangen levert misschien ook nog wat op, maar daar heb ik geen zin meer in):
PHP:
1
2
3
4
5
6
7
8
9
function glowmouse($arr) {
    $i = true;
    $new_arr = array();
    foreach($arr as $key => $val) {
        $i = !$i;
        if($i)    $new_arr[] = array($key_oud, $dit_oud, $dat_oud, $key, $val['dit'], $val['dat']);
        else { $key_oud = $key; $dit_oud = $val['dit']; $dat_oud = $val['dat']; }
    }
}

Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

Dat scheelt aanzienlijk. ;)

GlowMouse: 0.10816597938538

En je foreach vervangen zal ws langzamer zijn omdat je dan in php variabelen gaat veranderen. En dat is trager dan c dat af te laten handelen.

[ Voor 55% gewijzigd door Spockz op 09-03-2008 22:49 ]

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • GlowMouse
  • Registratie: November 2002
  • Niet online
Spockz schreef op zondag 09 maart 2008 @ 22:48:
En je foreach vervangen zal ws langzamer zijn omdat je dan in php variabelen gaat veranderen. En dat is trager dan c dat af te laten handelen.
Dat is inderdaad de intuitie, maar in praktijk onjuist. Wellicht dat het in een latere PHP functie ooit sneller wordt, maar voor performance is foreach momenteel niet de beste oplossing. Maar nogmaals, vaak valt er in deze code weinig winst te behalen, en heb je veel meer aan inzichtelijke code.

Acties:
  • 0 Henk 'm!

  • Spockz
  • Registratie: Augustus 2003
  • Laatst online: 21-09 10:08

Spockz

Live and Let Live

Lijkt me hier juist wel van toepassing. Want je zult je integers om moeten zetten naar characters. En dat elke zoveel keer weer.

C'est le ton qui fait la musique. | Blog | @linkedin
R8 | 18-55 IS | 50mm 1.8 2 | 70-200 2.8 APO EX HSM | 85 1.8


Acties:
  • 0 Henk 'm!

  • Voutloos
  • Registratie: Januari 2002
  • Niet online
Het is niet van toepasing, want jij weet gewoon helemaal niet of dit stukje code een hotspot in het script is. Ga gerust een stukje code dat misschien wel heel incidenteel en/of enkel met een kleine array aangeroepen wordt compleet onleesbaar maken, maar denk vooral niet dat je daar in het totaalplaatje iets mee op schiet. :z

Zaken als count() buiten een conditie kan je als automatisme goed doen en zijn niet schadelijk voor de leesbaarheid. Maar de tweaks welke ten koste gaan van de leesbaarheid moet je alleen inzetten als het er toe doet, en er geen elegantere oplossing is, zoals bijvoorbeeld een beter algoritme. :)

En van die benchmark link hierboven krijg ik al helemaal jeuk. Slecht uitgevoerde test, met slechte conclusies en verder totaal geen kijk op good/bad practice.

De TS wil leren hoe met bepaalde arrays om te gaan. Van een aantal hier genoemde micro optimalisaties leert hij echt niets goeds.

Executive summary: back ontopic please. ;)

{signature}

Pagina: 1