TL;DR
Given an array of arrays, I need to make sure that every array has the same length of the first.
The original problem
I have a function that should transpose a matrix lines to columns.
Original Result
1,2,3 1,4,7
4,5,6 2,5,8
7,8,9 3,6,9
How is the current implementation
I implemented it using array_map
:
<?php
$items = array_map(function (...$items) {
return $items;
}, ...$values);
What I need to achieve
When an array is shorter than the first I need to throw a LengthException
.
The ideal solution
The ideal solution would be storing the length of the first element outside the array_map and just compare with the length of the current item being iterated by array_map
, like this:
<?php
$expectedLength = count(reset($values));
$items = array_map(function (...$items) {
$length = count($items);
if ($length !== $expectedLength) {
throw new LengthException("Element size differs ({$length} should be {$expectedLength})");
}
return $items;
}, ...$values);
Why the ideal solution doesn't work
From the PHP manual:
Usually when using two or more arrays, they should be of equal length because the callback function is applied in parallel to the corresponding elements. If the arrays are of unequal length, shorter ones will be extended with empty elements to match the length of the longest.
Sadly, the shorter arrays will be filled with empty elements.
Since the original array could have empty elements, I'm left with no other way to test if the array was originally shorter than the first.
My first and cumbersome solution
I have to test it before array_map
and I'm not convinced that this is a good solution:
<?php
$expectedLength = count(reset($values));
$diffLength = count(array_intersect_key(...$values));
if ($diffLength !== $expectedLength) {
throw new LengthException("Element size differs ({$diffLength} should be {$expectedLength})");
}
$items = array_map(function (...$items) {
return $items;
}, ...$values);
Would you be kind enough to help me find a better way? I would like to do it inside the iteration, but if you find a better way to find if we have an element with a different length (I don't like to be using array_intersect_key
) before the iteration, that's OK too.