9

I need to merge several arrays into a single array. The best way to describe what I'm looking for is "interleaving" the arrays into a single array.

For example take item one from array #1 and append to the final array. Get item one from array #2 and append to the final array. Get item two from array #1 and append...etc.

The final array would look something like this:

array#1.element#1 array#2.element#1 . . .

The "kicker" is that the individual arrays can be of various lengths.

Is there a better data structure to use?

spdaly
  • 1,260
  • 2
  • 18
  • 35
  • 2
    Please explain further how you expect your result in the case where the arrays have various lengths. Would you stop the interleaving when one of the arrays have reached its last element or do you want the remaining arrays to continue to be interleaved until all arrays have reached their last element? – Oskar Dec 07 '09 at 15:07
  • 1
    This question is not terribly clear because we do not have a [mcve]. We cannot be sure if you are seeking "tranposition". If so, the canonical is: [Transposing multidimensional arrays in PHP](https://stackoverflow.com/q/797251/2943403) – mickmackusa Apr 23 '22 at 03:06

4 Answers4

31

for example,

function array_zip_merge() {
  $output = array();
  // The loop incrementer takes each array out of the loop as it gets emptied by array_shift().
  for ($args = func_get_args(); count($args); $args = array_filter($args)) {
    // &$arg allows array_shift() to change the original.
    foreach ($args as &$arg) {
      $output[] = array_shift($arg);
    }
  }
  return $output;
}

// test

$a = range(1, 10);
$b = range('a', 'f');
$c = range('A', 'B');
echo implode('', array_zip_merge($a, $b, $c)); // prints 1aA2bB3c4d5e6f78910
coredumperror
  • 8,471
  • 6
  • 33
  • 42
user187291
  • 53,363
  • 19
  • 95
  • 127
  • Great piece of code for sure! If anyone need a detailed step by step explanation how this function works, check out [this thread here](http://stackoverflow.com/questions/34482028/explain-how-this-custom-function-works-php) :) – Acidon Dec 27 '15 at 17:19
  • Note that `array_shift` is O(n), moves all elements up to fill the gap, traversing the whole array per call. In a nested loop, that's painful from a time complexity standpoint. Better to use `array_push` which is O(1), then do a one-off reverse of the result at the very end. A counter per array is another option that adds code complexity but is efficient and avoids mutating the input. – ggorlen Dec 17 '20 at 23:11
3

If the arrays only have numeric keys, here's a simple solution:

$longest = max( count($arr1), count($arr2) );
$final = array();

for ( $i = 0; $i < $longest; $i++ )
{
    if ( isset( $arr1[$i] ) )
        $final[] = $arr1[$i];
    if ( isset( $arr2[$i] ) )
        $final[] = $arr2[$i];
}

If you have named keys you can use the array_keys function for each array and loop over the array of keys instead.

If you want more than two arrays (or variable number of arrays) then you might be able to use a nested loop (though I think you'd need to have $arr[0] and $arr[1] as the individual arrays).

DisgruntledGoat
  • 70,219
  • 68
  • 205
  • 290
1

I would just use array_merge(), but that obviously depends on what exactly you do.

This would append those arrays to each other, while elements would only be replaced when they have the same non-numerical key. And that might not be a problem for you, or it might be possible to be solved because of attribute order, since the contents of the first arrays' elements will be overwritten by the later ones.

Franz
  • 11,353
  • 8
  • 48
  • 70
0

If you have n arrays, you could use a SortedList, and use arrayIndex * n + arrayNumber as a sort index.

Charles Bretana
  • 143,358
  • 22
  • 150
  • 216