3

I would like to take an array like this and combine it into 1 single array.

array (size=2)
   0 => 
      array (size=10)
         0 => string '1' 
         1 => string 'a' 
         2 => string '3' 
         3 => string 'c' 
   1 => 
      array (size=5)
         0 => string '2'
         1 => string 'b'

However I want the array results to be interleaved.

So it would end up looking like

array
     0 => '1'
     1 => '2'
     2 => 'a'
     3 => 'b'
     4 => '3'
     5 => 'c'

I would like it so that it doesn't matter how many initial keys are passed in (this one has 2), it should work with 1, 2 or 5. Also, as you can see from my example the amount of elements most likely won't match.

Anyone know the best way to accomplish this?

mickmackusa
  • 43,625
  • 12
  • 83
  • 136
Keith
  • 1,352
  • 3
  • 21
  • 48
  • Will array keys match or could they be completely random? For instance `[1,'a',3,'c']` and `[17 => 2, 9 => 'b']`? Must the resulting indexes be sequential? What exactly do you mean by initial keys? It looks like you want to transpose a matrix (switch columns and rows) which is sparsely populated. – knittl Sep 04 '14 at 15:26
  • 2
    I would suggest at least trying something first instead of flat out asking for code – ElefantPhace Sep 04 '14 at 15:28
  • @Keith: does this help? http://stackoverflow.com/questions/797251/transposing-multidimensional-arrays-in-php – knittl Sep 04 '14 at 15:32

4 Answers4

5
$data = array(
    0 => array(
        0 => '1',
        1 => 'a',
        2 => '3',
        3 => 'c',
    ),
    1 => array(
        0 => '2',
        1 => 'b',
    ),
);

$newArray = array();
$mi = new MultipleIterator(MultipleIterator::MIT_NEED_ANY);
$mi->attachIterator(new ArrayIterator($data[0]));
$mi->attachIterator(new ArrayIterator($data[1]));
foreach($mi as $details) {
    $newArray = array_merge(
        $newArray,
        array_filter($details)
    );
}
var_dump($newArray);
Mark Baker
  • 209,507
  • 32
  • 346
  • 385
  • This answer is missing its educational explanation. It is also not zero-safe because of the default behavior of `array_filter()`. – mickmackusa Aug 29 '21 at 22:38
  • This answer is [easily adjusted to accommodate more than 2 input arrays](https://3v4l.org/SUCTa). – mickmackusa Sep 04 '22 at 08:48
0

Tried to think of a fun solution:

$array = [
    ["a","b","c"],
    ["d","e"]
];
$result = [];
while($array) { 
    array_walk(
        $array, 
        function(&$subarray, $key) use (&$array, &$result) { 
            $result[] = array_shift($subarray); 
            if(empty($subarray)) unset ($array[$key]); 
        }
    );
}

var_dump($result);

It destroys the original array though.

Eugene
  • 3,280
  • 21
  • 17
0

I had fun with this... So if you like it use it!

$arr1 = [1,'a',3,'c'];
$arr2 = ['2','b'];

$finarry = arrayInterweave($arr1,$arr2);
print_r($finarry);

function arrayInterweave($arr1,$arr2){
  $count1 = count($arr1);
  $count2 = count($arr2);
  $length = (($count1 >= $count2) ? $count1 : $count2);

  $fin = array();
  for($i = 0;$i<$length;$i++){
      if(!empty($arr1[$i])){
        $fin[] = $arr1[$i];
      }
      if(!empty($arr2[$i])){
        $fin[] = $arr2[$i];
      }
  }
  return $fin;
}
Cayce K
  • 2,288
  • 1
  • 22
  • 35
  • also tested with longer second string `$arr2 = ['2','b',12,3123,2191,22,11,'a'];` – Cayce K Sep 04 '14 at 15:36
  • Note that it's a multidimensional array of variable amounts, not two arrays. – Ben Fortune Sep 04 '14 at 15:37
  • yea... actually just realized that as I wasn't paying attention. I'm going to see if I can fix it. But if someone submits something better than I will probably still fix mine! – Cayce K Sep 04 '14 at 15:39
  • So because @Don'tPanic did basically what I had to do with my solution as is without me changing it up too much I'm going to leave it be. I don't want to steal his. I can't think of anything currently that would be much better than either solutions above me. – Cayce K Sep 04 '14 at 15:54
  • This answer is missing its educational explanation. It is also not zero-safe because of the default behavior of `empty()`. – mickmackusa Aug 29 '21 at 22:39
0

After determining which row contains the most elements, you can loop through known indexes and push columns of data into the result array.

The following technique is safe to use with a variable number of rows.

Code: (Demo)

$maxCount = max(array_map('count', $array));
$result = [];
for ($i = 0; $i < $maxCount; ++$i) {
    array_push($result, ...array_column($array, $i));
}
var_export($result);

Input/Output:

$array $result
[['b', 'e', 'd', 's'], ['l', 'n']] ['b', 'l', 'e', 'n', 'd', 's']
['f', 'g', 'n', 's'], ['r', 'm'], ['a', 'e', 't'] ['f', 'r', 'a', 'g', 'm', 'e', 'n', 't' 's']

The above technique is perfectly capable of accommodating 3 or more input arrays as well.


p.s. For anyone running into technical limitations because their php version, this will do the same:

$maxCount = max(array_map('count', $array));
$result = [];
for ($i = 0; $i < $maxCount; ++$i) {
    foreach (array_column($array, $i) as $found) {
        $result[] = $found;
    }
}

...if your php version doesn't accommodate the above snippet, you really, really need to upgrade your php version (sorry, not sorry).


To avoid the counting to determine the longest subarray, you can instead transpose the data with nested loops then flatten that result structure. (Demo)

$result = [];
foreach ($array as $i => $row) {
    foreach ($row as $k => $v) {
        $result[$k][$i] = $v;
    }
}
 var_export(array_merge(...$result));
mickmackusa
  • 43,625
  • 12
  • 83
  • 136