代码之家  ›  专栏  ›  技术社区  ›  prodigitalson

递归合并数组而不覆盖重复键的最佳方法

  •  2
  • prodigitalson  · 技术社区  · 14 年前

    我有一个多维的表单数据数组,它是从YAML中未序列化的。因此,它看起来像这样:

    Array(
      'name' => 'Somone',
      'email' => 'someone@none.local',
      'billing' => Array(
         'address_1' => '1234 Somewhere'
         'address_2' => NULL,
         'city' => 'Somewhere',
         'state' => 'ST'
         'country' => 'CO'
         'postal_code' => '12345'
       ),
      'shipping' => Array(
         'address_1' => '1234 Somewhere'
         'address_2' => NULL,
         'city' => 'Somewhere',
         'state' => 'ST'
         'country' => 'CO'
         'postal_code' => '12345'
      )
    );
    

    我需要做的是把它展平,这样我就可以输出一些CSV,所以它应该是这样的:

    Array(
      'name' => 'Somone',
      'email' => 'someone@none.local',
      'billing_address_1' => '1234 Somewhere'
      'billing_address_2' => NULL,
      'billing_city' => 'Somewhere',
      'billing_state' => 'ST'
      'billing_country' => 'CO'
      'billing_postal_code' => '12345'
      'shipping_address_1' => '1234 Somewhere'
      'shipping_address_2' => NULL,
      'shipping_city' => 'Somewhere',
      'shipping_state' => 'ST'
      'shipping_country' => 'CO'
      'shipping_postal_code' => '12345'
    );
    

    我永远不知道数组/散列有多深-它可能只有2级,如图所示,也可能是5级。

    此外,这是在Symfony 1.4,因此sfForm及其所有的奢侈品,如果需要的话。我认为应该有一个明智的方法来使用小部件模式和小部件来实现这一点。但是,如果可能的话,我希望避免将数据绑定回表单。这不是实际表单提交过程的一部分,但在管理员下载提交数据集的操作中是完全独立的。

    3 回复  |  直到 14 年前
        1
  •  2
  •   halfdan    14 年前

    只是一个快速的破解,但效果相当不错:

    function array_flatten($array, $prefix = '') {
        $newArray = array();
        foreach($array as $key => $value) {
            if(is_array($value)) {
                    $newArray = array_merge($newArray, array_flatten($value, $key));
            }
            else {
                    $index = empty($prefix) ? $key : $prefix.'_'.$key;
                    $newArray[$index] = $value;
                 }
         }
         return $newArray;
    }
    

    测试:

    $a = array(
            "a" => "b",
            "ca" => array(
                "de" => "ef",
                "ef" => "gd"
            )
    );
    
    var_dump(array_flatten($a));
    
    // Output:
    /*
    
    array(3) {
      ["a"]=>
      string(1) "b"
      ["ca_de"]=>
      string(2) "ef"
      ["ca_ef"]=>
      string(2) "gd"
    }
    
    */
    
        2
  •  2
  •   lonesomeday    14 年前
    function flatten(Array $array, $name = '') {
        $ret = array();
    
        foreach ($array as $key => $value) {
            $itemname = ($name ? $name . '_' : '') . $key;
    
            if (is_array($value)) {
                $ret = array_merge($ret, flatten($value, $itemname));
            } else {
                $ret[$itemname] = $value;
            }
        }
    
        return $ret;
    }
    
        3
  •  1
  •   Chris Laplante    9 年前

    这个怎么样?我不知道你想怎么处理重复的钥匙,所以我把选择权留给你了。只要替换一下 ; // Do something here on duplicate key

    $info = Array(
        'name' => 'Someone',
        'email' => 'someone@none.local',
        'billing' => Array(
            'address_1' => '1234 Somewhere',
            'address_2' => NULL,
            'city' => 'Somewhere',
            'state' => 'ST',
            'country' => 'CO',
            'postal_code' => '12345'
        ),
        'shipping' => Array(
            'address_1' => '1234 Somewhere',
            'address_2' => NULL,
            'city' => 'Somewhere',
            'state' => 'ST',
            'country' => 'CO',
            'postal_code' => '12345'
        )
    );
    
    function explodeArray($array, &$data, $prefix = "") {
        foreach ($array as $key => $value) {
            if (is_array($value)) {
                explodeArray($value, $data, $prefix . $key . "_");
            } else {
                if (!array_key_exists($prefix . $key, $data)) {
                    $data[$prefix . $key] = $value;
                } else {
                    ; // Do something here on duplicate key
                }
            }
        }
    }
    
    $result = array();
    explodeArray($info, $result);
    
    print_r($result);