简体   繁体   English

将数组动态转换为键值对数组

[英]Dynamically convert array to key-value pair array

This is an example of array I have:这是我拥有的数组示例:

 $data = [
      'total_amount' => 200,
      'purchase_date' => '01.01.2020',
      'items' => [
           [
                'name' => 'T-shirt',
                'price' => 50
           ],
           [
                'name' => 'Jacket',
                'price' => 150
           ],
       ]
];

and I would like to get something like this:我想得到这样的东西:

$data = [
    [
        'k' => 'total_amount',
        'v' => 200
    ],
    [
        'k' => 'purchase_date',
        'v' => '01.01.2020'
    ]
    [
        'k' => 'items',
        'v' => [
           [
                [
                    'k' => 'name',
                    'v' => 'T-Shirt'
                ],
                [
                    'k' => 'price',
                    'v' => 50
                ]
           ],
           [
                [
                    'k' => 'name',
                    'v' => 'Jacket'
                ],
                [
                    'k' => 'price',
                    'v' => 150
                ]
           ]
        ]
    ]
]

It's not a big problem to parse the first array and then create desired output.解析第一个数组,然后创建所需的 output 问题不大。 Also, if we have nested and nasted and nested array, then I just use a recursion and it seems to work pretty good.此外,如果我们有嵌套和嵌套数组,那么我只使用递归,它似乎工作得很好。 Here is the code I have:这是我的代码:

public function convert(array $data) : array
{
    $output = [];

    foreach ($data as $k => $v) {
        if (is_array($v)) {
            $output[] = ['k' => $k, 'v' => $this->value($v)];
        } else {
            $output[] = ['k' => $k, 'v' => $v];
        }
    }

    return $output;
}

and the following:以及以下内容:

   protected function value($items)
{
    $output = [];
    $i = 0;

    foreach ($items as $itemK => $itemV) {
        if (!is_array($itemV)) {
            $output[$i] = ['k' => $itemK, 'v' => $itemV];
            continue;
        }

        foreach ($itemV as $k => $v) {
            if (is_array($v)) {
                $output[$i][] = ['k' => $k, 'v' => $this->value($v)];
                continue;
            }

            $output[$i][] = ['k' => $k, 'v' => $v];
        }

        $i++;
    }

    return $output;
}

The question is if there is a way to optimize this code without using too many foreach functions (maybe there is built-in PHP function that I can leverage) and maybe avoid recursion?问题是是否有一种方法可以在不使用太多 foreach 函数的情况下优化此代码(也许有内置的 PHP function 我可以利用)并且可能避免递归?

Here's a slightly simplified version of your code.这是您的代码的稍微简化的版本。 Note that if you want to allow arbitrarily nested key/value pairs, recursion is the only effective method to do that:请注意,如果您想允许任意嵌套的键/值对,递归是唯一有效的方法:

function convert($array) {
    $output = array();
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            // nested array with numeric keys? if so don't create a k,v pair
            if (is_numeric($key)) {
                $output[] = convert($value);
            }
            else {
                $output[] = array('k' => $key, 'v' => convert($value));
            }
        }
        else {
            $output[] = array('k' => $key, 'v' => $value);
        }
    }
    return $output;
}

Output: Output:

Array
(
    [0] => Array
        (
            [k] => total_amount
            [v] => 200
        )
    [1] => Array
        (
            [k] => purchase_date
            [v] => 01.01.2020
        )
    [2] => Array
        (
            [k] => items
            [v] => Array
                (
                    [0] => Array
                        (
                            [0] => Array
                                (
                                    [k] => name
                                    [v] => T-shirt
                                )
                            [1] => Array
                                (
                                    [k] => price
                                    [v] => 50
                                )
                        )
                    [1] => Array
                        (
                            [0] => Array
                                (
                                    [k] => name
                                    [v] => Jacket
                                )
                            [1] => Array
                                (
                                    [k] => price
                                    [v] => 150
                                )
                        )
                )
        )
)

Demo on 3v4l.org 3v4l.org 上的演示

To tighten-up / D.R.Y.-out your code, identify the processes that are written more than once and try to refactor the script in a way that will permit the single declaration of a function call or process.为了收紧/D.R.Y.-out 您的代码,识别多次编写的进程并尝试以允许 function 调用或进程的单一声明的方式重构脚本。

  1. You know that you will need to use recursion when $value is an array, so conditionally call&cache the recursion's return value to a variable.你知道当$value是一个数组时你需要使用递归,所以有条件地调用&缓存递归的返回值到一个变量。
  2. You know that you will need need to push the new associative structure into the output array when the key is not an index, so conditionally push what is needed.您知道当键不是索引时,您需要将新的关联结构推送到 output 数组中,因此有条件地推送需要的内容。

Using the following, you get your desired output without redundant scripting.使用以下内容,您将获得所需的 output 而无需冗余脚本。

Code: ( Demo )代码:(演示

function restructure($array) {
    $output = [];
    foreach ($array as $key => $value) {
        if (is_array($value)) {
            $value = restructure($value);
        }
        $output[] = is_int($key) ? $value : ['k' => $key, 'v' => $value];
    }
    return $output;
}

var_export(restructure($data));

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM