【问题标题】:Explain how this array transposing and flattening function works解释这个数组转置和展平函数是如何工作的
【发布时间】:2015-12-27 15:47:24
【问题描述】:

这里的 PHP 函数允许合并任意 N 个不同长度的数组,输出数组将按下一个顺序排列:Array1[0],Array2[0],..,ArrayN[0],Array1[1],Array2[1],..,ArrayN[1]...

    function array_zip_merge() {
      $output = array();
      // The loop incrementer takes each array out of the loop as it gets emptied by array_shift().
      for ($args = func_get_args(); count($args); $args = array_filter($args)) {
        // &$arg allows array_shift() to change the original.
        foreach ($args as &$arg) {
          $output[] = array_shift($arg);
        }
      }
      return $output;
    }

// test

$a = range(1, 10);
$b = range('a', 'f');
$c = range('A', 'B');
echo implode('', array_zip_merge($a, $b, $c)); // prints 1aA2bB3c4d5e6f78910

虽然我了解此示例中的每个内置函数各自的作用,但我无法理解它们如何在此函数中协同工作,尽管包含解释性评论...

有人可以帮我分解一下吗?该功能按原样工作得很好,只是让我发疯,我不明白它是如何工作的......

P.S:此函数取自Interleaving multiple arrays into a single array问题。

【问题讨论】:

  • 自己写一个类似的函数,它会让你知道什么是必要的。很有可能你最终会自己重写上面的代码。也就是说,在不同的执行点检查上述代码中变量的内容,以了解它的作用。

标签: php function transpose flatten array-filter


【解决方案1】:

数组 $a$b$c 分别有 10、6 和 2 个元素。

$a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10];
$b = ['a', 'b', 'c', 'd', 'e', 'f'];
$c = ['A', 'B'];

当您将数组作为array_zip_merge() 函数的参数提供时,请查看for 循环。 func_get_args() 将设置 $args 并提供所有参数。在第一次 for 循环运行开始时,

$args = [$a, $b, $c];
count($args) = 3;

foreach 循环中,array_shift 将返回每个数组的第一个元素,从而使$output 类似于

$output = [1, 'a', 'A'];

数组现在看起来像,

$a = [2, 3, 4, 5, 6, 7, 8, 9, 10];
$b = ['b', 'c', 'd', 'e', 'f'];
$c = ['B'];

在第一个for 循环结束时,array_filter 函数将测试任何数组是否为空,并将其从$args 中删除。在第二次运行时也会发生同样的事情,在第二次 for 循环结束时,变量看起来像

$a = [3, 4, 5, 6, 7, 8, 9, 10];
$b = ['c', 'd', 'e', 'f'];
$c = [];
$output = $output = [1, 'a', 'A', 2, 'b', 'B'];
//because $c is empty array_filter() removes it from $args
$args = [$a, $b];

因此,在 for 循环的第三次迭代中,count($args) 将返回 2。当$b 的最后一个元素被array_shift 删除时,count($args) 将返回1。迭代会一直持续到所有数组都为空

【讨论】:

  • 感谢您提供如此详细的答案,您一步一步的迭代清除了我脑海中的东西,最后一切都开始变得有意义了:)))
【解决方案2】:

array_zip_merge 中,for 语句总是将每个数组的第一个值分别添加到output 变量中。

因为 array_shift 删除了它返回的元素,所以在每个循环中,第一个元素都是不同的。当它因此而变空时,循环无事可做并中断。

如果你还是不明白,请询问你遇到问题的代码的具体部分。

【讨论】:

    【解决方案3】:

    自定义函数实际上是一种转置和展平技术,可容纳非矩阵数据集。所谓非矩阵,我的意思是将三个数组推入一个数组,数据集中会有柱状间隙。使用 implode(array_merge(...array_map(null, $a, $b, $c))) will work by happenstance (因为您正在使用空字符串作为粘合来内爆数据,但在其他情况下,空元素的生成可能会扭曲结果。

    我发现借来的脚本很难解释。 for 循环将比foreach() 简单得多。可以在函数定义中使用扩展运算符将传入的列数据声明为变量,而不是调用func_get_args()

    这是执行 3 步任务的一种方法(没有内爆):

    1. 转置 3 个数组中的数据(隔离数据列)
    2. 从列数据中过滤空值
    3. 展平过滤后的二维数组 (array_merge(...$tranposedAndfiltered))

    代码:(Demo)

    var_export(
        array_merge(
            ...array_map(
                fn(...$col) => array_filter(
                    $col,
                    fn($v) => !is_null($v)
                ),
                $a,
                $b,
                $c
            )
        )
    );
    

    如果在没有展开运算符和空值过滤的情况下执行转置更简单,则只需在展平和内爆之前使用嵌套的 foreach 循环。 (Demo)

    $output = [];
    foreach ([$a, $b, $c] as $i => $array) {
        foreach ($array as $k => $v) {
            $output[$k][$i] = $v;
        }
    }
    var_export(implode(array_merge(...$output)));
    

    查看 Stack Overflow 的数组转置规范:Transposing multidimensional arrays in PHP

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2011-02-16
      • 2014-07-20
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-09-11
      • 2013-03-13
      相关资源
      最近更新 更多