【问题标题】:Dynamically convert array to key-value pair array将数组动态转换为键值对数组
【发布时间】:2020-08-25 14:32:26
【问题描述】:

这是我拥有的数组示例:

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

我想得到这样的东西:

$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
                ]
           ]
        ]
    ]
]

解析第一个数组然后创建所需的输出并不是什么大问题。此外,如果我们有嵌套和嵌套数组,那么我只使用递归,它似乎工作得很好。 这是我的代码:

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

以及以下内容:

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

问题是是否有一种方法可以在不使用太多 foreach 函数的情况下优化此代码(也许有我可以利用的内置 PHP 函数)并避免递归?

【问题讨论】:

    标签: php recursion


    【解决方案1】:

    要收紧/删除您的代码,请确定多次编写的进程,并尝试以允许函数调用或进程的单一声明的方式重构脚本。

    1. 您知道当$value 是一个数组时需要使用递归,因此有条件地调用并缓存递归的返回值到一个变量。
    2. 您知道,当键不是索引时,您需要将新的关联结构推送到输出数组中,因此有条件地推送需要的内容。

    使用以下内容,您无需多余的脚本即可获得所需的输出。

    代码:(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));
    

    【讨论】:

    • 感谢您的支持。这是实现期望的最棒和最干净的方式。
    【解决方案2】:

    这是您的代码的略微简化版本。请注意,如果您想允许任意嵌套的键/值对,递归是唯一有效的方法:

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

    输出:

    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

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-02-14
      • 1970-01-01
      • 2014-01-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2017-08-25
      相关资源
      最近更新 更多