user3358052
user3358052

Reputation: 9

Chunk and transpose a flat array into rows with a specific number of columns

An array of values are provided in the order they should appear in columns. For example, the second value in the array should be displayed on a webpage beneath the first instead of on its right.

Task: Reorder the array so that the values are in the order they will be output in html. The data for the first row must be first in the output.

Example inputs:

$input = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; 
$cols = 2;

Example output:

[['A', 'E'], ['B','F'], ...]

Upvotes: 0

Views: 176

Answers (3)

mickmackusa
mickmackusa

Reputation: 47894

The modern functional equivalent of @billyonecan's approach uses the spread operator to transpose the data after it has been "chunked" to the correct size. (Demo)

$input = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; 
$cols = 2;

var_export(
    array_map(
        null,
        ...array_chunk($input, ceil(count($input) / 2))
    )
);
// [['A', 'E'], ['B', 'F'], ['C', 'G'], ['D', null]]

A classic loop alternative using a modulus calculation is also attractive because it doesn't generate the extra null element in the final set when the division doesn't come out even: (Demo)

$input = ['A', 'B', 'C', 'D', 'E', 'F', 'G']; 
$cols = 2;

$rows = ceil(count($input) / $cols);
$result = [];
foreach ($input as $i => $value) {
    $result[$i % $rows][] = $value;
}
var_export($result);
// [['A', 'E'], ['B', 'F'], ['C', 'G'], ['D']]

On this related topic, to more simply chunk and transpose with a finite number of rows, use the following: (Demo)

$rows = 2;
var_export(
    array_map(
        null,
        ...array_chunk($input, $rows)
    )
);

Upvotes: 0

billyonecan
billyonecan

Reputation: 20260

Use array_chunk() to break the array up in to $cols:

$chunks = array_chunk($array, ceil(count($array) / $cols));

Which would give you:

array(array('A', 'B', 'C', 'D'), array('E', 'F', 'G'));

Then combine the values from each array where the keys match.

array_unshift($chunks, null);
$chunks = call_user_func_array('array_map', $chunks);

// array(array('A', 'E'), array('B', 'F'), array('C', 'G'), array('D', NULL))

Here's an example

Upvotes: 1

marian0
marian0

Reputation: 3337

You need to count offset and then iterate over an array:

$input = array('A', 'B', 'C', 'D', 'E', 'F', 'G');
$cols = 2;
$itemsCount = count($input);
$offset = ceil($itemsCount/$cols);

$result = array();
for($i = 0; $i < $itemsCount; ++$i) {
    if (isset($input[$i]) && isset($input[$i + $offset])) {
        $result[] = array($input[$i], $input[$i + $offset]);
    }
}

Upvotes: 0

Related Questions