You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

PHP嵌套repeat数组转换:为元素添加正确repeat计数属性

问题:处理嵌套repeat/close_repeat数组的转换

需求说明

现有数组A包含repeat和close_repeat类型的特殊对象:

  • repeat对象带有number属性,指定其与对应close_repeat之间元素的重复次数
  • 支持嵌套结构,嵌套时重复次数为各层number的乘积

需要将数组A转换为数组B:

  • 移除所有repeat和close_repeat对象
  • 为其余元素添加repeat属性,标记该元素应重复的次数(例如示例中id为8的元素repeat值为3*2=6)

示例数组

Array A

[
   {
      "id":1,
      "type":"title",
      "data": "Title goes here"
   },
   {
      "id":2,
      "type":"repeat",
      "number":3
   },
   {
      "id":3,
      "type":"media",
      "data": "path to media"
   },
   {
      "id":4,
      "type":"close_repeat"
   },
   {
      "id":5,
      "type":"repeat",
      "number":3
   },
   {
      "id":6,
      "type":"title",
      "data": "Title goes here"
   },
   {
      "id":7,
      "type":"repeat",
      "number":2
   },
   {
      "id":8,
      "type":"text",
      "data": "Text goes here"
   },
   {
      "id":9,
      "type":"close_repeat"
   },
   {
      "id":10,
      "type":"close_repeat"
   },
   {
      "id":11,
      "type":"cover",
      "data": "Cover data goes here"
   }
]

Array B

[
   {
      "id":1,
      "type":"title",
      "data": "Title goes here",
      "repeat":1
   },
   {
      "id":3,
      "type":"media",
      "data": "path to media",
      "repeat":1
   },
   {
      "id":6,
      "type":"title",
      "data": "Title goes here",
      "repeat":3
   },
   {
      "id":8,
      "type":"text",
      "data": "Text goes here",
      "repeat":6
   },
   {
      "id":11,
      "type":"cover",
      "data": "Cover data goes here",
      "repeat":1
   }
]

现有尝试代码(存在问题)

public function loopOver($data, &$newData, &$repeat, &$previousRepeat, $i){
        $dataCount = count($data);
 
        for( ; $i<$dataCount; $i++){

            if($data[$i]['type']=='repeat'){
                $previousRepeat = $data[$i]['number'];
                $repeat = $repeat * $data[$i]['number'];
                return $this->loopOver($data, $newData, $repeat, $previousRepeat, $i+1);
            }

            if($data[$i]['type']=='close_repeat'){
                $repeat = $repeat/$previousRepeat;
                return $this->loopOver($data, $newData, $repeat, $previousRepeat, $i+1);
            }

            if($i >= $dataCount){
                return $newData;
            }

            $tmpData = $data[$i];
            $tmpData['repeat'] = $repeat;
            $newData [] = $tmpData;

        }
        
    }

问题分析

原代码的核心问题:

  1. 使用单个previousRepeat变量保存上一层的重复次数,嵌套时会被覆盖,导致回溯计算错误
  2. 递归中使用return会中断当前循环,后续元素无法继续处理
  3. 依赖引用传递维护状态,逻辑容易混乱

正确解决方案

使用栈结构来维护嵌套的重复次数上下文,栈的先进后出特性完美匹配嵌套结构的层级关系:

public function processRepeatArray($data) {
    $newData = [];
    $repeatStack = [1]; // 栈保存每一层进入repeat前的重复次数,初始默认1
    $currentRepeat = 1;

    foreach ($data as $item) {
        switch ($item['type']) {
            case 'repeat':
                // 进入新的repeat层,先保存当前重复次数到栈
                array_push($repeatStack, $currentRepeat);
                // 更新当前重复次数为乘积
                $currentRepeat *= $item['number'];
                break;
            case 'close_repeat':
                // 退出repeat层,恢复到上一层的重复次数
                $currentRepeat = array_pop($repeatStack);
                break;
            default:
                // 普通元素,添加当前重复次数属性
                $newItem = $item;
                $newItem['repeat'] = $currentRepeat;
                $newData[] = $newItem;
                break;
        }
    }

    return $newData;
}

逻辑说明

  1. 初始时currentRepeat为1,栈中默认存入1,对应最外层无重复的情况
  2. 遇到repeat时:将当前的currentRepeat压入栈,然后将currentRepeat乘以当前repeat的number,进入嵌套层
  3. 遇到close_repeat时:弹出栈顶的数值,赋值给currentRepeat,回到上一层的重复次数状态
  4. 普通元素直接添加repeat属性为当前的currentRepeat,加入结果数组

这个方案能正确处理任意深度的嵌套结构,计算出准确的重复次数。

内容的提问来源于stack exchange,提问作者lari107k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.10 09:46:01