Php 强制数组长度相等 TL;博士

Php 强制数组长度相等 TL;博士,php,arrays,Php,Arrays,给定一个数组,我需要确保每个数组的长度与第一个数组的长度相同 原始问题 我有一个函数,可以将矩阵行转换为列 Original Result 1,2,3 1,4,7 4,5,6 2,5,8 7,8,9 3,6,9 目前的实施情况如何 我使用array\u map实现了它: <?php $items = array_map(function (...$items) { return $items; }, ...$values)

给定一个数组,我需要确保每个数组的长度与第一个数组的长度相同

原始问题 我有一个函数,可以将矩阵行转换为列

 Original     Result
  1,2,3       1,4,7
  4,5,6       2,5,8
  7,8,9       3,6,9
目前的实施情况如何 我使用
array\u map
实现了它:

<?php
$items = array_map(function (...$items) {
    return $items;
}, ...$values);
为什么理想的解决方案不起作用 从PHP手册:

通常在使用两个或多个数组时,它们的长度应该相等,因为回调函数与相应的元素并行应用。如果数组长度不等,则较短的数组将使用空元素扩展,以匹配最长数组的长度

遗憾的是,较短的数组将被空元素填充

由于原始数组可能有空元素,因此我没有其他方法来测试该数组最初是否比第一个数组短

我的第一个麻烦的解决方案 我必须在
array\u map
之前测试它,我不相信这是一个好的解决方案:

<?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);

只需稍作调整即可保持理想的解决方案:

array_map(function (...$items) {
    $nonNullItems = array_filter(
        $items,
        function ($item) { return $item !== null }
    );
    $length = count($nonNullItems);
    if ($length !== $expectedLength) {
        throw new LengthException(
            "Element size differs ({$length} should be {$expectedLength})"
        );
    }
    return $items;
}
注意这一补充:

array_filter($items, function ($item) { return $item !== null});
它将过滤掉项目中的所有空元素(但不是0或.0)

编辑:我不确定,但是
array\u filter($items)
可能也可以工作,但我不确定如果没有回调,是否会取消空项或空项,因此上面的操作将确保只取消空项。

代码:()

输出:

Test #0:
@0 originalsize (12) = rotatedsize (12)
Test #1:
@1 originalsize (11) DOES NOT EQUAL rotatedsize (12)
Test #2:
@2 originalsize (11) DOES NOT EQUAL rotatedsize (12)
Test #3:
@3 originalsize (11) DOES NOT EQUAL rotatedsize (12)
Test #4:
@4 originalsize (12) = rotatedsize (12)


---

Test #0:
The first size (3) = subarray 1 size (3)
The first size (3) = subarray 2 size (3)

Test #1:
The first size (3) = subarray 1 size (3)
The first size (3) DOES NOT EQUAL subarray 2 size (2)

Test #2:
The first size (3) DOES NOT EQUAL subarray 1 size (2)
The first size (3) = subarray 2 size (3)

Test #3:
The first size (2) DOES NOT EQUAL subarray 1 size (3)
The first size (2) DOES NOT EQUAL subarray 2 size (3)

Test #4:
The first size (3) = subarray 1 size (3)
The first size (3) = subarray 2 size (3)

“较短的元素将扩展为空元素”–测试“空元素”不起作用…?原始元素可能是空的,空性测试不会告诉我是数组映射填充了间隙还是原始值。然后在实际操作员之前进行健全性测试确实是正确的做法。它还使实际的
array\u map
操作更简单,并且更好地坚持单一责任原则。为什么您确实需要将其放在
array\u map()
中?在转置数组之前知道长度不是更好吗?!还可以查看
array\u reduce()
,使用它可以遍历每个数组,获取长度,一旦长度变短或变长,您就可以检测到它。您还可以使用a并将所有子数组附加为数组迭代器,然后您可以简单地根据每个子数组的元素数量转置数组。如果我错了,请纠正我:如果原始元素之一已为null,您将丢弃它?是的。array_filter也会丢弃这些值。但是如果您允许空值,则不使用空值填充另一个数组不是正确的/预期的行为?不适用于该特定操作,但是你让我想到,如果我有长度大于第一个数组的数组,我是否应该抛出一个异常。@阿尔瓦罗吉马尔(ÁlvaroGuimarães)我对这个问题感兴趣,但也许我误解了目标。请看一看我的两种方法,让我知道我是否达到了你想要的结果,或者是否有什么不符合简要说明。
$arrays=[
    [['a','b','c'],['d','e','f'],['g','h','i']],   // test array #1: no missing elements
    [['a','b','c'],['d','e','f'],['g','h']],       // test array #2: missing element i
    [['a','b','c'],['d','e'],['g','h','i']],       // test array #3: missing element f
    [['a','b'],['d','e','f'],['g','h','i']],       // test array #4: missing element c
    [['a','b','c'],['d','e','f'],['g','h',NULL]],  // test array #5: NULL on i
];

// find non-specific imbalance using COUNT_RECURSIVE
foreach($arrays as $i=>$a){  // running 5 separate tests
    echo "Test #$i:\n";
    if(($originalsize=sizeof($a,1))===($rotatedsize=sizeof(array_map(function(){return func_get_args();},...$a),1))){
        echo "@$i originalsize ($originalsize) = rotatedsize ($rotatedsize)\n";
    }else{
        echo "@$i originalsize ($originalsize) DOES NOT EQUAL rotatedsize ($rotatedsize)\n";
    }
}

echo "\n\n---\n\n";

// Find specific subarray imbalances using COUNT
foreach($arrays as $i1=>$a){  // running 5 separate tests
    echo "Test #$i1:\n";
    $firstsize=sizeof($a[0]);
    foreach(array_slice($a,1,null,true) as $i2=>$others){
        if($firstsize==($othersize=sizeof($others))){
            echo "The first size ($firstsize) = subarray $i2 size ($othersize)\n";
        }else{
            echo "The first size ($firstsize) DOES NOT EQUAL subarray $i2 size ($othersize)\n";
        }
    }
    echo "\n";
}
Test #0:
@0 originalsize (12) = rotatedsize (12)
Test #1:
@1 originalsize (11) DOES NOT EQUAL rotatedsize (12)
Test #2:
@2 originalsize (11) DOES NOT EQUAL rotatedsize (12)
Test #3:
@3 originalsize (11) DOES NOT EQUAL rotatedsize (12)
Test #4:
@4 originalsize (12) = rotatedsize (12)


---

Test #0:
The first size (3) = subarray 1 size (3)
The first size (3) = subarray 2 size (3)

Test #1:
The first size (3) = subarray 1 size (3)
The first size (3) DOES NOT EQUAL subarray 2 size (2)

Test #2:
The first size (3) DOES NOT EQUAL subarray 1 size (2)
The first size (3) = subarray 2 size (3)

Test #3:
The first size (2) DOES NOT EQUAL subarray 1 size (3)
The first size (2) DOES NOT EQUAL subarray 2 size (3)

Test #4:
The first size (3) = subarray 1 size (3)
The first size (3) = subarray 2 size (3)