Teretto
Teretto

Reputation: 655

Split flat array into equally-sized transposed chunks

I need to split array for 4 arrays next way. How can I do it more elegant? Each element goes to subarray while parent array not empty.

$mainblocks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
$sliders = [];

$slider_index = 0;
foreach ($mainblocks as $mainblock) {
    $sliders[$slider_index][] = $mainblock;
    if ($slider_index >= 3) {
        $slider_index = 0;
        continue;
    }
    $slider_index++;
}

print_r($sliders);

The expected output is: [[1,5,9] [2,6,10] [3,7,11] [4,8,12]]

Upvotes: 0

Views: 144

Answers (2)

mickmackusa
mickmackusa

Reputation: 47902

You want to chunk and transpose.

Here is a one-liner using array_map() and the splat operator (...) to unpack the chunks. Notice that if the chunks aren't even, you get NULL placeholding elements.

If you don't want NULL placeholders, you'll need to use foreach loops instead of array_map.

Code: (Demo)

$mainblocks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];

var_export(array_map(null, ...array_chunk($mainblocks, 4)));

echo "\n---\n";

$mainblocks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];

var_export(array_map(null, ...array_chunk($mainblocks, 4)));

Output:

array (
  0 => 
  array (
    0 => 1,
    1 => 5,
    2 => 9,
  ),
  1 => 
  array (
    0 => 2,
    1 => 6,
    2 => 10,
  ),
  2 => 
  array (
    0 => 3,
    1 => 7,
    2 => 11,
  ),
  3 => 
  array (
    0 => 4,
    1 => 8,
    2 => 12,
  ),
)
---
array (
  0 => 
  array (
    0 => 1,
    1 => 5,
    2 => 9,
  ),
  1 => 
  array (
    0 => 2,
    1 => 6,
    2 => 10,
  ),
  2 => 
  array (
    0 => 3,
    1 => 7,
    2 => NULL,
  ),
  3 => 
  array (
    0 => 4,
    1 => 8,
    2 => NULL,
  ),
)

If you want to traverse the input array only once and NOT create null elements, you can push elements based on a modulus calculation with the desired row size. Demo

$size = intdiv(count($mainblocks), 3);
$result = [];
foreach ($mainblocks as $i => $v) {
    $result[$i % $size][] = $v;
}
var_export($result);

Upvotes: 2

Aniket Sahrawat
Aniket Sahrawat

Reputation: 12937

Take a look at array_chunk():

$input_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
print_r(array_chunk($input_array, 3)); // output: [[1,2,3],[4,5,6],[7,8,9],[10,11,12]]

Description:

array_chunk ( array $array , int $size [, bool $preserve_keys = FALSE ] ) : array

Chunks an array into arrays with size elements. The last chunk may contain less than size elements.

Edit:

For your requirements:

$mainblocks = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12];
for($i = 0; $i <= sizeof($mainblocks) / 4; $i++)
    for($j = 1; $j <= sizeof($mainblocks); $j = $j + 4)
        $sliders[$i][] = $mainblocks[$j - 1 + $i];
print_r($sliders); // output: [[1,5,9] [2,6,10] [3,7,11] [4,8,12]]

Upvotes: 2

Related Questions