Andrew Cheong
Andrew Cheong

Reputation: 30273

PHP: Is there an elegant way to foreach through multiple items (groups) at a time?

Given an array of N items:

$arr = array('a', 'b', 'c', 'd', 'e', 'f');

What's the most elegant way to loop through in groups of M items (assuming N is divisible by M)?

I tried

foreach (array_chunk($arr, 2) as list($first, $second)) {
    // do stuff with $first and $second
}

but this resulted in a syntax error.

In other words, I want to emulate what in Tcl would look like this:

set arr [a b c d e f]
foreach {first second} $arr {
    // do stuff with $first and $second
}

For now I've resorted to the obvious measure:

foreach (array_chunk($arr, 2) as $group) {
    $first  = $group[0];
    $second = $group[1];
    // do stuff with $first and $second
}

But I'm hoping someone has a more elegant method...

Upvotes: 1

Views: 445

Answers (5)

Mark Baker
Mark Baker

Reputation: 212412

Possibly a case to take advantage of SPL's multipleIterator:

$arr = array('a', 'b', 'c', 'd', 'e', 'f');
$chunks = array_chunk($arr, 2);

$iterator = new MultipleIterator;
foreach($chunks as $chunk) {
    $iterator->attachIterator(new ArrayIterator($chunk));
}

foreach ($iterator as $values) {
    var_dump($values[0], $values[1], $values[2]);
}

Upvotes: 0

air4x
air4x

Reputation: 5683

You can use array_splice

while ( list($first, $second) = array_splice($arr, 0, 2) ) {
  echo $first.', '.$second.PHP_EOL;
}

It will throw a notice when $arr becomes empty

while ( !empty($arr) && list($first, $second) = array_splice($arr, 0, 2) ) {
  echo $first.', '.$second.PHP_EOL;
}

But this will still throw a notice if the size of the array is odd.

Upvotes: 1

Shiplu Mokaddim
Shiplu Mokaddim

Reputation: 57650

No, there is no syntactic sugar like the way you wanted. However their are many ways to achieve this.

For loop

for($i=0; $first=$arr[$i], $second=$arr[$i+1], $i<$len; $i+=2){
}

Foreach loop

foreach (array_chunk($arr, 2) as $chunk) {
    list($first, $second) = $chunk;
}

See the foreach form. Its not much different than your syntax.

While loop

$i=0;
while(list($first, $second) = array_slice($arr, ($i+=2)-2, 2)) {
}

Upvotes: 2

bukart
bukart

Reputation: 4906

I'd alter your last variant to

foreach (array_chunk($arr, 2) as $group) {
    list( $first, $second) = $group;
    // do stuff with $first and $second
}

Any other solution I thought about, would be more complex, like

for ( $i = 0; $i < ceil(count($arr)/2) ; $i++) {
    $first = $arr[$i*2];
    $second = $arr[$i*2+1];
}

Upvotes: 2

boobiq
boobiq

Reputation: 3024

You can use it like this

$arr = array('a', 'b', 'c', 'd', 'e', 'f');

$chunks = array_chunk($arr, 2);
while (list($first, $second) = each($chunks))
{
    ...
}

if you put array_chunk() into each() it will produce an infinite loop :(

Upvotes: 2

Related Questions