13

I am trying to arrange two arrays together and the results keep coming out incorrect. I'll show you my code, the results I'm getting and the results I'm looking for.

I guess I'm just doing it wrong but not sure how else to do it.

My code:

$data1 = [
    'a: 1',
    'a: 2',
    'a: 3',
    'a: 4',
    'a: 5'
];

$data2 = [
    'b: 1',
    'b: 2',
    'b: 3',
    'b: 4',
    'b: 5'
];


foreach($data1 as $item1)
{
    foreach($data2 as $item2)
    {
        echo $item1 . '<br/>';
        echo $item2 . '<br/>';
        echo '<br/><br/>';
    }
}

The Results: (shortened to save space)

a: 1
b: 1

a: 1
b: 2

a: 1
b: 3

a: 1
b: 4

a: 1
b: 5

The results I'm looking for is the following:

a: 1
b: 1

a: 2
b: 2

a: 3
b: 3

a: 4
b: 4

a: 5
b: 5
Rizier123
  • 58,877
  • 16
  • 101
  • 156
Exploit
  • 6,278
  • 19
  • 70
  • 103

2 Answers2

33

Problem

Well the problem is of course your nested foreach loop. Because for each element of your $data1 array you loop through the entire $data2 array (So in total there are $data1 * $data2 iterations).


Solutions

To solve this you have to loop through both arrays at once.

array_map() method (PHP >=5.3)

You can do this with array_map() and pass all arrays to it which you want to loop through at the same time.

array_map(function($v1, $v2){
    echo $v1 . "<br>";
    echo $v2 . "<br><br>";
}, $data1, $data2 /* , Add more arrays if needed manually */);

Note: If the amount of elements are uneven you won't gen any errors, it will just print NULL (Means you won't see anything)

MultipleIterator method (PHP >=5.3)

Use a MultipleIterator and attach as many ArrayIterator as you need.

$it = new MultipleIterator();
$it->attachIterator(new ArrayIterator($data1));
$it->attachIterator(new ArrayIterator($data2));
//Add more arrays if needed 

foreach($it as $a) {
    echo $a[0] . "<br>";
    echo $a[1] . "<br><br>";
}

Note: If the amount of elements are uneven it will just print all values where both arrays still have values

for loop method (PHP >=4.3)

Use a for loop with a counter variable, which you can use as key for both arrays.

$keysOne = array_keys($data1);
$keysTwo = array_keys($data2);

$min = min(count($data1), count($data2));

for($i = 0; $i < $min; $i++) {
    echo $data1[$keysOne[$i]] . "<br>";
    echo $data2[$keysTwo[$i]] . "<br><br>";
}

Note: Using array_keys() is just so that this also works if the arrays don't have the same keys or are associative. min() is used to only loop through as many elements as every array has

array_combine() method (PHP >=5.0)

Or if the arrays only have unique values, you can array_combine() both arrays, so that $data1 can be accessed as key and $data2 as value.

foreach(array_combine($data1, $data2) as $d1 => $d2) {
    echo $d1 . "<br>";
    echo $d2 . "<br><br>";
}

Note: The arrays must have the same amount of elements, otherwise array_combine() will throw an error

call_user_func_array() method (PHP >=5.6)

If you want to print more than 2 arrays at the same time or just an unknown amount of arrays, you can combine the array_map() method with a call_user_func_array() call.

$func = function(...$numbers){
    foreach($numbers as $v)
        echo $v . "<br>";
    echo "<br>";
};
call_user_func_array("array_map", [$func, $data1, $data2]);

Note: Since this kinda uses the array_map() method, it behaves the same with uneven amount of elements. Also since this method only works for PHP >=5.6 you can just remove the arguments and change out $numbers with func_get_args() in the foreach loop and then it also works for PHP >=5.3

Community
  • 1
  • 1
Rizier123
  • 58,877
  • 16
  • 101
  • 156
  • i've having this weird issue, instead of echoing the values i'm using array_push($somevar, ['item1' => $item1, 'item2' => $item2]); but the $somevar unregisters as an array within the array_map() function. and i had set it as an array outside of the iteration function. – Exploit Aug 18 '15 at 08:12
  • @SarmenB. Please post a little link to an online IDE or so with your current code. – Rizier123 Aug 18 '15 at 08:55
  • its ok i got it to work with MultipleIterator. But here is the code anyway http://pastie.org/private/ppeu5xre2khelnidsowpq – Exploit Aug 18 '15 at 09:03
  • i meant array_push not array_merge (when you see the snippet) – Exploit Aug 18 '15 at 09:06
  • @SarmenB. So first problem is, that the variable: `$collection` is out of scope in your anonymous function. To solve it you can use [`use()`](http://php.net/manual/en/functions.anonymous.php) and pass it by reference, so you won't lose the data in each call. And if you use `array_push()`, then everything else is correct, or do it like this: http://3v4l.org/6DEKO (just without array_push) – Rizier123 Aug 18 '15 at 09:12
  • 1
    nice thanks! i'm starting to like the subject of arrays now, it was on subject i would avoid when i was a noob. – Exploit Aug 18 '15 at 09:16
  • btw, do you know of an alternative to array_map when iterating objects? I'm looking through php.net to see if i see anything myself – Exploit Aug 18 '15 at 09:26
  • @SarmenB. *objects* Depends what structure they have and what you want to display. – Rizier123 Aug 18 '15 at 09:31
  • using the sample above as an object instead of an array – Exploit Aug 18 '15 at 09:36
  • @SarmenB. Then it would get more complicated, especially when you have numbers as property names and when the object also would come from an array. – Rizier123 Aug 18 '15 at 09:50
7

use key from 1 to get row in 2

foreach($data1 as $k=> $item1)
{
        echo $item1 . '<br/>';
        echo $data2[$k] . '<br/>';
        echo '<br/><br/>';
}