0

如何用array_walk替换嵌套数组中的值?

这是我的数组,

$item = array(
    "id" => "2",
    "title" => "parent 2",
    "children" => array (
           "id" => "4",
           "title" => "children 1"
        )
);

//replacement array:
$replace = [
  '2' => 'foo',
  '4' => 'bar',
  '7' => 'baz'
];

我的工作职能,

function myfunction(&$value,$key,$replace)
{   

    if(isset($replace[$key]))
    {
       $value = $replace[$key];
    }

    if(is_array($key))
    {
        array_walk($value,"myfunction",$replace);
    }
}

array_walk($item,"myfunction",$replace);

print_r($item);

结果,

Array
(
    [id] => 2
    [title] => parent 2
    [children] => Array
        (
            [id] => 4
            [title] => children 1
        )

)

我追求的结果,

Array
(
    [id] => 2
    [title] => foo
    [children] => Array
        (
            [id] => 4
            [title] => bar
        )

)
4

3 回答 3

2

这个递归函数可以帮助你

function replace($item,$replace)
{
    foreach ($replace as $key => $value) 
    {
        if($item["id"]==$key)
            $item["title"] = $value;
        if(isset($item['children']))
            $item['children'] = replace($item['children'],$replace);
    }
    return $item;
}

它不修改 $item,它返回它修改后,所以你需要这样调用它

$item = replace($item,$replace);

为了让你的函数修改参数 $item,只需像这样通过引用传递它:

function replace(&$item,$replace)
{
    foreach ($replace as $key => $value) 
    {
        if($item["id"]==$key)
            $item["title"] = $value;
        if(isset($item['children']))
            replace($item['children'],$replace);
    }
}

在这种情况下,您只需要像这样调用函数:

replace($item,$replace);
print_r($item);
于 2014-07-20T15:58:20.350 回答
0

试试这个功能:

    function replaceKey($subject, $newKey, $oldKey) {

    if (!is_array($subject)) return $subject;

    $newArray = array(); // empty array to hold copy of subject
    foreach ($subject as $key => $value) {

        // replace the key with the new key only if it is the old key
        $key = ($key === $oldKey) ? $newKey : $key;

        // add the value with the recursive call
        $newArray[$key] = $this->replaceKey($value, $newKey, $oldKey);
    }
    return $newArray;
}
于 2021-05-18T05:28:28.713 回答
0

这可能会或可能不会感觉有点不正统。我的方法是通过使用json_encode()将多维数组展平为一个非常可预测的字符串来消除处理多维数组的麻烦,然后使用preg_replace()替换正确的值,然后使用json_decode()生成所需的关联数组. 我相信您会发现遵循该程序非常简单。

输入:

$item = array(
    "id" => "2",
    "title" => "parent 2",
    "children" => array ( "id" => "4", "title" => "children 1" )
);
$replace=['2'=>'foo','4'=>'bar','7'=>'baz'];

代码(演示):

foreach($replace as $k=>$v){
    $pattern[]="/(?<=\"id\":\"$k\",\"title\":\")[^\"]*/";
}
$item=json_encode($item);
$item=preg_replace($pattern,$replace,$item);
var_export(json_decode($item,true));

输出:

array (
  'id' => '2',
  'title' => 'foo',
  'children' => 
  array (
    'id' => '4',
    'title' => 'bar',
  ),
)

每当有人使用这种技术来修改数组的键或值时,绝对不能将要替换的子字符串与另一个子字符串混淆。幸运的是,对于您的输入数组,该结构非常干净且可预测。

也就是说,我编写的模式在匹配值的双引号之前匹配从id键到id值到键的 json 语法。对于您的案例,这将是一个非常值得信赖的模式。titletitle

$pattern如果您对数组中的正则表达式模式感到好奇:

array (
  0 => '/(?<="id":"2","title":")[^"]*/',  # \
  1 => '/(?<="id":"4","title":")[^"]*/',  # --- Mostly positive lookbehind, then match
  2 => '/(?<="id":"7","title":")[^"]*/',  # /
)

现在,如果你足够勇敢地将我的函数堆叠在一起以使用更少的代码行并避免额外$item声明

代码(演示):

foreach($replace as $k=>$v){
    $pattern[]="/(?<=\"id\":\"$k\",\"title\":\")([^\"]*)/";
}
var_export(json_decode(preg_replace($pattern,$replace,json_encode($item)),true));
于 2017-05-08T12:28:23.380 回答