【问题标题】:Merge a multidimensional array and retain non-empty values when possible合并多维数组并尽可能保留非空值
【发布时间】:2017-09-21 07:51:48
【问题描述】:

我有一个具有这种结构的关联数组(实际上是一个 Laravel 集合):

$array = [
    ["firstname" => "John", "lastname" => "",      "email" => "",                 "uri" => ""],
    ["firstname" => "",     "lastname" => "Smith", "email" => "",                 "uri" => ""],
    ["firstname" => "",     "lastname" => "",      "email" => "john@example.org", "uri" => ""]
];

如何组合/合并/减少整个多维数组,以便最终得到一个包含所有列并优先考虑非空值的扁平结构?

类似这样的:

[
    ['firstname' => 'John', 'lastname' => 'Smith', 'email' => 'john@example.org', 'uri' => '']
]

【问题讨论】:

    标签: php arrays multidimensional-array merge reduction


    【解决方案1】:

    我将展示一些具有不同优点的替代技术,这些技术依赖于所有列都表示在所有行中这一事实。我看不出生成二维输出数组有什么好处,所以我所有的 sn-ps 都会生成相同的平面关联数组。

    无论您喜欢哪种样式,至少需要两个循环——一个用于迭代行,一个用于迭代每行中的元素。

    标准嵌套循环:(Demo)

    $result = array_shift($array);  // remove the first row and push it into the result array
    foreach ($array as $row) {
        foreach ($row as $key => $value) {
            if ($value !== '') {
                $result[$key] = $value;  // only overwrite where a non-empty value exists
            }
        }
    }
    var_export($result);
    

    基于半函数的迭代:(Demo)

    $result = array_shift($array);  // remove the first row and push it into the result array
    foreach ($array as $row) {
        $result = array_merge($result, array_filter($row, 'strlen')); //  merge only non-empty elements into the result
    }
    var_export($result);
    

    *注意,如果您的实际项目有超过您发布的四个字段并且其中一个字段可能包含您不想过滤掉的零值,请使用strlen作为array_filter() 中的参数。否则,array_filter() 将贪婪地杀死 null、false、zeroish 和零宽度值。


    基于array_reduce()的全功能:(Demo)

    var_export(
        array_reduce(
            $array,
            function($carry, $row) {
                $carry = array_merge($carry, array_filter($row, 'strlen'));
                return $carry;
            },
            array_shift($array)
        )
    );
    

    基于全功能的array_merge_recursive(): (Demo)

    var_export(
        array_map('max', array_merge_recursive(...$array))
    );
    

    这是最简短的,但是 - 不可否认 - 利用 max() 将从每一列返回所需的字符串这一事实。作为一种通用技术,这种方法可能并不适合所有场景。

    实际上,这是将$array 解包为$row[0], $row[1], $row[2](使用...),然后将数据转换为列数据的子数组(使用array_merge_recursive() 维护第一级键),然后将每个子数组减少到其“最高" 值(在每个子数组上使用 max())。


    Sahil 的答案不是很可靠/不可靠,因为它会在流程完成后手动更正缺少的 uri 密钥值。这种调整纯粹是因为缺失值对程序员来说是“已知的”。从编程上讲,这是懒惰的,容易失败,不应该被 SO 读者使用。

    【讨论】:

      【解决方案2】:

      这里我们使用array_mergearray_filterarray_merge 将一个数组合并到另一个数组中,array_filter 将过滤数组中的空值。

      Try this code snippet here

      <?php
      
      $array = array(
          0 => array(
              "firstname" => "John",
              "lastname" => "",
              "email" => "",
              "uri" => ""
          ),
          1 => array(
              "firstname" => "",
              "lastname" => "Smith",
              "email" => "",
              "uri" => ""
          ),
          2 => array(
              "firstname" => "",
              "lastname" => "",
              "email" => "john@example.org",
              "uri" => "")
      );
      $result=array();
      foreach($array as $value)
      {
          $result=  array_merge($result,array_filter($value));
      }
      $result["uri"]="";
      print_r(array($result));
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 2015-12-27
        • 2016-12-14
        • 2017-12-19
        • 2011-03-14
        • 2013-05-23
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多