简体   繁体   English

如何递归搜索和替换未知深度多维 PHP 数组中的值?

[英]How can I recursively search for and replace values inside of an unknown-depth multidimensional PHP array?

I'm working with a JSON string.我正在使用 JSON 字符串。 I'm converting it to an associative array to find specific values and change those values when a certain key is found (['content']).我将其转换为关联数组以查找特定值并在找到特定键时更改这些值 (['content'])。 The depth of the array is always unknown and will always vary.数组的深度总是未知的,并且总是会变化。

Here is the function I wrote.这是我写的function。 It takes an array as an argument and passes it by reference so that the variable itself is modified rather than a copy of it scoped locally to that function.它采用一个数组作为参数并通过引用传递它,这样变量本身就会被修改,而不是它的副本在本地作用域为 function。

$json_array = json_decode($json_string, true);

function replace_data(&$json_array, $data='REPLACE TEST')
{
   foreach($json_array as $key => $value) {
       if ($key == 'content' && !is_array($value)) {
           $json_array[$key] = $data;

       } else {
           if (is_array($value)) {
               replace_data($value, $data);
           }
       }
   }

}


replace_data($json_array, "test test test");
var_dump($json_array);

What I'm expecting to happen is every time a key ['content'] is found at no matter what depth, it replaces with that value specified in the $data argument.我期望发生的是,无论在什么深度,每次找到键 ['content'] 时,它都会替换为 $data 参数中指定的值。

But, when I var_dump($json_array) Those values are unchanged.但是,当我var_dump($json_array)这些值没有改变。

What am I missing?我错过了什么?

With array_walk_recursive : 使用array_walk_recursive

function replace_data($json_array, $data = 'REPLACE TEST') {
    array_walk_recursive($json_array, function (&$value, $key) use ($data) {
        if (!is_array($value) && $key === 'content') {
            // $value passed by reference
            $value = $data;
        }
    });
    return $json_array;
}

And without references: 并且没有参考:

function replace_data($json_array, $data = 'REPLACE TEST') {
    foreach ($json_array as $key => $value) {
        if (is_array($value)) {
            $json_array[$key] = replace_data($value, $data);
        } elseif ($key === 'content') {
            $json_array[$key] = $data;
        }
    }
    return $json_array;
}

To expand on my comment, you need another reference here: 要扩展我的评论,您需要在这里另外参考:

foreach($json_array as $key => &$value) {

That way, a reference to the original value is passed when you make the recursive call, rather than the local copy created with the foreach loop. 这样,在进行递归调用时将传递对原始值的引用,而不是使用foreach循环创建的本地副本。

From the PHP manual entry for foreach : foreachPHP手册中

In order to be able to directly modify array elements within the loop precede $value with &. 为了能够直接在循环内修改数组元素,在$ value之前加&。 In that case the value will be assigned by reference. 在这种情况下,该值将通过引用分配。

You'll also see in the manual that it recommends unsetting the reference to $value after the loop. 您还将在手册中看到它建议您在循环后将对引用的设置取消为$value Even though it probably won't cause any problems if you don't do that in your function, it's best to be in the habit of always unsetting references created in foreach loops like that. 即使您在函数中不这样做也不会引起任何问题,但最好还是养成始终取消设置在诸如此类的foreach循环中创建的引用的习惯。 It can cause some strange looking problems if you don't. 如果不这样做,可能会导致外观有些奇怪

From PHP7.4, "arrow function" syntax offers a clean and short approach.从 PHP7.4 开始,“箭头函数”语法提供了一种简洁的方法。

As leafnodes are iterated, if the key is content , then replace the text, otherwise do not change the value.随着叶节点的迭代,如果键是content ,则替换文本,否则不更改值。

There are no return s being used.没有使用return All mutations are applied directly to the passed in variables prefixed with & .所有突变都直接应用于以&为前缀的传入变量。

function replace_data(&$array, $replaceWith = 'REPLACE TEST')
{
   array_walk_recursive(
        $array,
        fn(&$v, $k) => $v = ($k === 'content' ? $replaceWith : $v)
    );
}

replace_data($json_array, "test test test");
var_export($json_array);

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

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