我有这个数组:

        $data = [
            [
                "id"=>1,
                "data"=>"data 1",
            ],
            [
                "id"=>2,
                "data"=>"data <4>",
            ],
            [
                "id"=>3,
                "data"=>"data 3",
            ],
            [
                "id"=>4,
                "data"=>"<3>",
            ]
        ];

我想生产一种新的array.生成的数组应为:

[
    {
        "id": 1,
        "data": "data 1"
    },
    {
        "id": 2,
        "data": "data data 3"
    },
    {
        "id": 3,
        "data": "data 3"
    },
    {
        "id": 4,
        "data": "data 3"
    }
]

其思想是,每当data属性中有<number>时,该值应该被具有相同id的元素中的data属性所替换.在上面的示例中,最后一个元素是:

            [
                "id"=>4,
                "data"=>"<3>",
            ]

因此,我们用data 3替换<3>,因为它是用id:3存储在Element的data属性中的.

我已经创建了一个使用上述数组的函数:

    public function refProcess($data, &$newData, $i, &$tmpData){
        $dataLength = count($data);
        if($i>=$dataLength){
            return;
        }
        for(;$i<$dataLength;$i++){
            if(is_null($tmpData)){
                $tmpData = ['id'=> $data[$i]['id'], 'data'=>null];
            }

            if(strpos($data[$i]['data'],"[")!==false){

                $parsed = $this->getInbetweenStrings("<", ">", $data[$i]['data']);
                if(count($parsed)){

                    foreach($parsed as $occurance){
                        foreach($data as $key => $dataValue){
                            if($dataValue['id']==$occurance){

                                if(strpos($dataValue['data'], "<")!==false){

                                    $this->refProcess($data, $newData, $key, $tmpData);
                                    $tmpData=null;
                                }
                                else{
                                    
                                    $tmpDataAtt = str_replace("<".$occurance.">", $dataValue['data'], $data[$i]['data']);
                                    $tmpData['data'] = $tmpDataAtt;
                                    $newData [] = $tmpData;
                                    $tmpData = null;
                                    break;
                                }
                            }
                        }
                        
                    }
                }
            }
            else{
                $tmpData['data'] = $data[$i]['data'];
                $newData [] = $tmpData;
                $tmpData = null;
            }
        }//foreach
    }


   //returns an array contains strings existing between $start and $end. Multiple occurance
  public function getInbetweenStrings($start, $end, $str){
        $matches = array();
        $regex = "/$start([a-zA-Z0-9_]*)$end/";
        preg_match_all($regex, $str, $matches);
        return $matches[1];
    }

它工作得很好.但问题是,一旦我向数组中添加了另一个元素:

        $data = [
            [
                "id"=>1,
                "data"=>"data 1",
            ],
            [
                "id"=>2,
                "data"=>"data <4>",
            ],
            [
                "id"=>3,
                "data"=>"data 3",
            ],
            [
                "id"=>4,
                "data"=>"<3>",
            ],
            [
                "id"=>5,
                "data"=>"<2>",
            ]
        ];

元素为id:5,则函数进入死循环.我遗漏了什么?

该代码可以在https://onlinephp.io/c/0da5d℃进行测试

推荐答案

你实际上没有做任何递归的事情,你有一个退出的平面数组 struct .

更新:这是错误的,只留作相关 comments :

<?php

$data = [
    ["id" => 1, "data" => "data 1",],
    ["id" => 2, "data" => "data <4>",],
    ["id" => 3, "data" => "data 3",],
    ["id" => 4, "data" => "<3>",],
    ["id" => 5, "data" => "<2>",]
];
foreach ($data as &$set) {
    $set['data'] = preg_replace_callback('#.*(\d+).*#', function ($m) {
         return 'data ' . $m[1];
    },$set['data']);
}
print_r($data);

最新情况: 现在有一个可行的解决方案.

<?php

$data = [
    ["id" => 1, "data" => "data 1",],
    ["id" => 2, "data" => "data <4>",],
    ["id" => 3, "data" => "data 3",],
    ["id" => 4, "data" => "<3>",],
    ["id" => 5, "data" => "<2>",],
    ["id" => 6, "data" => "data <7>",],#loop to 7
    ["id" => 7, "data" => "<6>",],#loop to 6
    ["id" => 8, "data" => "<0>",],#dead link
    ["id" => 9, "data" => "<10>",],#multi level loop
    ["id" => 10, "data" => "data <11>",],#multi level loop
    ["id" => 11, "data" => "<9>",],#multi level loop
];
#just for testing: order can be ignored
shuffle($data);
#step 1 make keys easy to access
$prepared = [];
$tmp=[];
foreach ($data as $set) {
    $prepared[$set['id']] = $set['data'];
    $tmp[$set['id']] = $set;
}
$data=$tmp;
#setp 2 replace values
$final = [];
do {
    foreach ($data as $k => &$set) {
        $set['data'] = preg_replace_callback('#(.*)<(\d+)>#', function ($m) use ($prepared,$k) {
            #check for dead links
            if(!isset($prepared[$m[2]])){
                return $m[1]." ?{$m[2]}?";
            }
            #check for loop refer
            if(strpos($prepared[$m[2]],"<".$k.">")!==false){
                return $m[1]." §{$m[2]}§";
            }
            return $m[1].$prepared[$m[2]];
        }, $set['data']);
    
        if (strpos($set['data'], '>') === false) {
            $final[$k] = $set;
            unset($data[$k]);
        }
        
    }
 
} while (count($data));
ksort($final);
print_r($final);

更新:

  1. 现在判断死链接或循环并标记它们.
  2. 添加了更多的准备代码,因此现在可以忽略顺序

Php相关问答推荐

为WooCommerce中的特定用户角色指定促销价格

一列必须指定多个变量的Laravel查询

在ShipStation for WooCommerce中使用自定义订单项目元数据

在特定日期之间使用特定的元密钥销售产品

WooCommerce/WordPress:简单的产品属性显示

通过DO LAMP进行身份验证并从邮箱发送邮箱的最简单方式是什么

在冲突和几何上插入的Postgres参数化查询在PHP中不起作用

无额外字段的Laravel同步

Azure应用程序无法访问共享文件夹

如何在codeigniter中将order_by RAND与下面的代码一起使用

隐藏WooCommerce管理子菜单;主页;来自store 经理

Laravel withOnly不限制查询

PHP向API发送curl请求

Laravel Eloquent:复杂的多对多关系以及缺失关系的默认值

PHP Loop 在迭代中使用修改后的数据

如何在光速网络服务器中使用 apache ..htaccess

Eloquent 的模型更新了它应该 laravel php 的更多行

列表不在 GROUP BY 子句中并且包含 X2CRM 中的非聚合列

我正在使用 Baryryvdh/laravel-snappy 从 HTML 导出 PDF 它正在工作但缩小了 pdf 文件

fopen 功能不断向我发送我重新加载网页时已发布的重复版本的表单