duanhuang7591 2018-09-28 00:12
浏览 83
已采纳

PHP 7 - 在回调中迭代填充多级数组

I need to build complex multilevel array in callback only, one atomic update per call.

The reason for it: callback is called many times from iterative parser. Finally it should build deserialized PHP-array of binary format being parsed.

Here is runnable code:

const ACTION_VALUE = 1;
const ACTION_ENTER = 2;
const ACTION_LEAVE = 3;

function callback($action, $value, &$param)
{
   switch ($action) 
   {
    case ACTION_ENTER:
        $param['parent'][] = &$param['current'];
        $param['current'][] = [];

        end($param['current']);                
        $param['current'] = &$param['current'][key($param['current'])];
    break;

    case ACTION_LEAVE:
        unset($param['current']);
        $param['current'] = array_pop($param['parent']);
        end($param['current']);
    break;

    case ACTION_VALUE:
        $param['current'][] = $value;
    break;
   }
}

// prepare container
$arr = [];
$arr['data'] = [];
$arr['current'] = &$arr['data'];
$arr['parent'] = [];

// callback invocations
callback(ACTION_VALUE, 1, $arr);
callback(ACTION_VALUE, 2, $arr);
callback(ACTION_ENTER, 0, $arr);
callback(ACTION_VALUE, 10, $arr);
callback(ACTION_VALUE, 11, $arr);
callback(ACTION_LEAVE, 0, $arr);
callback(ACTION_VALUE, 3, $arr);
callback(ACTION_VALUE, 4, $arr);

// now see result
var_dump(json_encode($arr['data']));

Try it here

Above example prints:

[1,2,[10,11]], but should [1,2,[10,11],3,4].

Update: Multilevel means arbitrary arrays of random depth.

Update: The problem was with array_pop(), see below accepted answer for fixed version.

  • 写回答

2条回答 默认 最新

  • dongpu1315 2018-09-28 10:49
    关注

    I think the problem is array_pop which doesn't return actual reference to the last element. This one works:

    <?php
    
    const ACTION_VALUE = 1;
    const ACTION_ENTER = 2;
    const ACTION_LEAVE = 3;
    
    function callback($action, $value, &$param)
    {
        switch ($action) {
            case ACTION_ENTER:
                $param['parent'][] = &$param['current'];
                $param['current'][] = [];
    
                end($param['current']);
                $param['current'] = &$param['current'][key($param['current'])];
                break;
    
            case ACTION_LEAVE:
                unset($param['current']);
                end($param['parent']);
                $param['current'] = &$param['parent'][key($param['parent'])];
                unset($param['parent'][key($param['parent'])]);
                end($param['current']);
                break;
    
            case ACTION_VALUE:
                $param['current'][] = $value;
                break;
        }
    }
    
    // prepare container
    $arr = [];
    $arr['data'] = [];
    $arr['current'] = &$arr['data'];
    $arr['parent'] = [];
    
    // callback invocations
    callback(ACTION_VALUE, 1, $arr);
    callback(ACTION_VALUE, 2, $arr);
    callback(ACTION_ENTER, 0, $arr);
    callback(ACTION_VALUE, 10, $arr);
    callback(ACTION_VALUE, 11, $arr);
    callback(ACTION_ENTER, 0, $arr);
    callback(ACTION_VALUE, 40, $arr);
    callback(ACTION_VALUE, 41, $arr);
    callback(ACTION_LEAVE, 0, $arr);
    callback(ACTION_LEAVE, 0, $arr);
    callback(ACTION_VALUE, 3, $arr);
    callback(ACTION_VALUE, 4, $arr);
    
    // now see result
    var_dump(json_encode($arr['data']));
    
    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论
查看更多回答(1条)

报告相同问题?

悬赏问题

  • ¥15 一个服务器已经有一个系统了如果用usb再装一个系统,原来的系统会被覆盖掉吗
  • ¥15 使用esm_msa1_t12_100M_UR50S蛋白质语言模型进行零样本预测时,终端显示出了sequence handled的进度条,但是并不出结果就自动终止回到命令提示行了是怎么回事:
  • ¥15 前置放大电路与功率放大电路相连放大倍数出现问题
  • ¥30 关于<main>标签页面跳转的问题
  • ¥80 部署运行web自动化项目
  • ¥15 腾讯云如何建立同一个项目中物模型之间的联系
  • ¥30 VMware 云桌面水印如何添加
  • ¥15 用ns3仿真出5G核心网网元
  • ¥15 matlab答疑 关于海上风电的爬坡事件检测
  • ¥88 python部署量化回测异常问题