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

发布于 2024-09-24 06:26:46 字数 1596 浏览 1 评论 0原文

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

Array(
  'name' => 'Somone',
  'email' => '[email protected]',
  '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' => '[email protected]',
  '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 及其所有奢侈品。我认为应该有一种明智的方法来使用小部件架构和小部件来做到这一点。但是,如果可能的话,我想避免将数据绑定回表单。这不是实际表单提交过程的一部分,而是完全独立于管理员下载提交的数据集的操作。

I have a multidimensional array of form data thats an been unserialized from YAML. As such it looks something like this:

Array(
  'name' => 'Somone',
  'email' => '[email protected]',
  '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'
  )
);

What i need to do is to flatten this so I can output some CSV, so it should look something like this:

Array(
  'name' => 'Somone',
  'email' => '[email protected]',
  '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'
);

I will never know for sure how deep the array/hash is - it coul be only 2 levels as shown here or it could be 5.

Also this is in Symfony 1.4 so the sfForm with all of its luxuries is available if needed. I'm thinking there should be a sensible way to do this using the widget schema(s) and widgets. However, i would like to avoid binding the data back to the form if possible. This isn't part of the actual form submission process but is completely separate in an action for admins to download sets of the submitted data.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

〃安静 2024-10-01 06:26:46

只是一个快速破解,但效果很好:

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

*/

Just a quick-hack but it works pretty good:

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

Test:

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

*/
放低过去 2024-10-01 06:26:46
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;
}
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;
}
年华零落成诗 2024-10-01 06:26:46

这个怎么样?我不知道你想如何处理重复的键,所以我把这个选项留给你。只需替换 ; // 使用您自己的代码在重复键上执行某些操作

$info = Array(
    'name' => 'Someone',
    'email' => '[email protected]',
    '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);

How about this? I didn't know how you wanted to handle duplicate keys, so I left that option up to you. Just replace ; // Do something here on duplicate key with your own code.

$info = Array(
    'name' => 'Someone',
    'email' => '[email protected]',
    '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);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文