drti52047 2014-08-05 17:41
浏览 19
已采纳

PHP递归语法

I've never done recursions before and I feel I might be missing something. This code works but seems more "wordy" than it needs to be. Seems like I've seen people doing do..while's for recursion, but I'm not sure how/if it would apply here.

resolve($array) is supposed to replace any "{% tags %}" with the appropriate string from the same $array, and repeat the process in case of nesting. Simplified as best I could - hope this makes sense:

<?php

$strings = [
    "title":"My Program",
    "first_string":"<b>{% title %}:</b> The second_string text is {% second_string %}",
    "second_string"=>"Hello, World! Do you like {% title %}?"
];

function resolve($strings) {

    $regex = "/{% ([^{}]*?) %}/"; //RegEx for getting {% tags %}

    foreach($strings as $str_key=>$str_val) {
        //if the string has any {% tags %}...
        if(preg_match_all($regex,$str_val,$tmp_tags_arr)) {
            list($tags,$tagNames) = $tmp_tags_arr;
            foreach($tagNames as $tag_key=>$tag_name) //for every tagname...
                $strings[$str_key] = str_replace(
                    $tags[$tag_key],
                    $strings[$tag_name],
                    $strings[$str_key]
                    ); //replace the whole {% tag %} with appropriate value
        }
    }

    /*****This part just seems overly redundant******/

    //Rerun all the $strings to check if there are still unresolved {% tags %}
    foreach($strings as $str_key=>$str_val)
        if(preg_match_all($regex,$str_val,$tags))
            $strings = resolve($strings);

    return $strings;

}

var_dump(resolve($strings));
// Returns:
// array (size=3)
//   'title' => string 'My Program' (length=10)
//   'first_string' => string '<b>My Program:</b> The second_string text is Hello, World!' (length=58)
//   'second_string' => string 'Hello, World! Do you like My Program?' (length=13)

?>

My question is: what is the more appropriate way to do a recursion like this?

Edit:

$strings['first_string'] references 'title' and 'second_string', but 'second_string' includes a {% tag %} itself... hence the need for recursion.

  • 写回答

1条回答 默认 最新

  • duanqian1888 2014-08-05 18:09
    关注

    No recursion necessary since the keys must be unique and we know what they are, just loop through those. As str_replace takes arrays, you can replace on the entire array each time through the loop:

    foreach(array_keys($strings) as $tag) {
        $strings = str_replace("{% $tag %}", $strings[$tag], $strings);
    }
    print_r($strings);
    

    The value of array_keys($strings) is 'title', 'first_string', 'second_string', so the loop proceeds like this:

    Iteration 1: Searches for {% title %} in the entire array and replaces it with its value from $strings

    $strings = [
        "title"=>"My Program",
        "first_string"=>"<b>My Program:</b> The second_string text is {% second_string %}",
        "second_string"=>"Hello, World! Do you like My Program?"
    ];
    

    Iteration 2: Searches for {% first_string %} in the entire array and replaces it with its value from $strings

    $strings = [
        "title"=>"My Program",
        "first_string"=>"<b>My Program:</b> The second_string text is {% second_string %}",
        "second_string"=>"Hello, World! Do you like My Program?"
    ];
    

    Iteration 3: Searches for {% second_string %} in the entire array and replaces it with its value from $strings

    $strings = [
        "title"=>"My Program",
        "first_string"=>"<b>My Program:</b> The second_string text is Hello, World! Do you like My Program?",
        "second_string"=>"Hello, World! Do you like My Program?"
    ];
    

    DEMO

    本回答被题主选为最佳回答 , 对您是否有帮助呢?
    评论

报告相同问题?

悬赏问题

  • ¥15 有了解d3和topogram.js库的吗?有偿请教
  • ¥100 任意维数的K均值聚类
  • ¥15 stamps做sbas-insar,时序沉降图怎么画
  • ¥15 unity第一人称射击小游戏,有demo,在原脚本的基础上进行修改以达到要求
  • ¥15 买了个传感器,根据商家发的代码和步骤使用但是代码报错了不会改,有没有人可以看看
  • ¥15 关于#Java#的问题,如何解决?
  • ¥15 加热介质是液体,换热器壳侧导热系数和总的导热系数怎么算
  • ¥100 嵌入式系统基于PIC16F882和热敏电阻的数字温度计
  • ¥15 cmd cl 0x000007b
  • ¥20 BAPI_PR_CHANGE how to add account assignment information for service line