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

时间:2010-09-17 21:30:41

标签: php csv recursion symfony-forms

我有一个多维数组的表单数据,这些数据是从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 个答案:

答案 0 :(得分:2)

只是一个快速的黑客但它的效果非常好:

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"
}

*/

答案 1 :(得分:2)

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;
}

答案 2 :(得分:1)

这个怎么样?我不知道你想如何处理重复键,所以我把这个选项留给你了。只需使用您自己的代码替换; // 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);