【问题标题】:PHP recursive version of function any improvement?PHP递归版函数有什么改进?
【发布时间】:2018-03-19 23:54:27
【问题描述】:

我创建了一个可以转换数组的 PHP 函数:

[
    'one/two' => 3,
    'one/four/0' => 5,
    'one/four/1' => 6,
    'one/four/2' => 7,
    'eight/nine/ten' => 11,
]

转入以下 JSON 字符串:

{
    "one":
    {
        "two": 3,
        "four": [ 5,6,7]
    },
    "eight":
    {
        "nine":
        {
            "ten":11
        }
    }
}

函数如下:

<?php
function toJsonStr($array) {

    $final_array = [];

    foreach ($array as $key => $value) {

        $key_exploded = explode("/", $key);

        $array_index_at_end = is_numeric(end($key_exploded)) ? true : false ;

        if ($array_index_at_end === true) {
            $array_index = array_pop($key_exploded);
        }

        $ref = &$final_array;
        foreach ($key_exploded as $value2) {

            if (!isset($ref[$value2])) {
                $ref[$value2] = [];
            }

            $ref = &$ref[$value2];
        }

        if ($array_index_at_end === true) {
            $ref[$array_index]=$value;
        } else {
            $ref=$value;
        }
    }

    return json_encode($final_array);
}


$array = [
    'one/two' => 3,
    'one/four/0' => 5,
    'one/four/1' => 6,
    'one/four/2' => 7,
    'eight/nine/ten' => 11,
];

$json_str = toJsonStr($array);

echo "\n";
print_r($json_str);
echo "\n\n";

我几乎肯定这也可以递归完成。我是递归新手,在创建递归版本时无法构建方法。

创建递归版本是否值得?与我上面实现的 foreach 中的简单 foreach 相比,也许它太难理解了?

我知道递归算法可以简化代码并使代码更紧凑,但在这种情况下是否值得?

【问题讨论】:

  • 阅读stackoverflow.com/questions/5250733/…。这里有一些有趣的回应可能有用
  • 1)在大多数情况下,递归速度较慢,并且占用了更多的堆栈。递归的主要优点是,对于像树遍历这样的问题,它使算法更容易或更“优雅”。 2)表达性 大多数问题自然地用递归来表达,例如斐波那契、归并排序和快速排序。在这方面,代码是为人类而不是机器编写的。考虑到以上几点,可能递归版本在这种情况下并不好。我想我应该只保留我拥有的 foreach。

标签: php recursion


【解决方案1】:

恕我直言,如果您的输入数组的结构可以具有嵌套结构,那么递归方法将是有意义的:

[
'one/two' => 3,
'one/four/0' => 5,
'one/four/1' => 6,
'one/four/2' => 7,
'eight/nine/ten' => 11,
'eleven/twelve' => [
  'thirteen/fourteen' => 15,
  'sixteen/seventeen' => 18,
  'nineteen/twenty' => [
    'twentyone/twentytwo' => 23
    ],
  ],
]

那么你应该为此实现一个递归函数。当您不需要实现时,请保持简单。

【讨论】:

  • 是的,这是有道理的,因为我最近在使用递归的堆栈公民的帮助下解决了一个问题。这种情况在对象中有未知数量的嵌套对象(类似于您在上面描述的情况)。递归使该算法更加紧凑和易于消化。在这种特定情况下,由于没有嵌套结构,我将遵循您的建议并保持简单。仅仅为了它而把事情复杂化是不明智的。
【解决方案2】:

它可以更短,尽管我通常不使用递归来执行此操作,因为深度无关紧要。您已经掌握了参考文献。见How to access and manipulate multi-dimensional array by key names / path?

function toJsonStr($array, &$result=array()) {
    foreach($array as $key => $value) {
        $path = explode('/', $key);
        $temp =& $result;    
        foreach($path as $key) {
            $temp =& $temp[$key];
        }
        $temp = $value;
    }
    $result = json_encode($result);
}

toJsonStr($array, $result);

【讨论】:

  • 是的,这样更好——就这样吧。 T.Y.
  • 最初我构建它时在对象中添加对象(stdClass),但 JSON 在编码时将 PHP 关联数组视为相同的对象键:值,因此切换到数组。这可以解释 !isset() 被留在里面。
  • 按引用传递“&”在函数参数列表中没有空格并且在函数体中的变量赋值中的变量之间有一个空格是什么意思?
  • @ponytails_soda:没有意义,可以是$temp = &amp;$result;。由于某种原因,我习惯了在某个地方以另一种方式进行操作。
  • 泰。我一直看到人们这样做,我想知道这是否是公认的最佳做法。
猜你喜欢
  • 2020-10-03
  • 2011-02-27
  • 2012-06-07
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-10-14
  • 1970-01-01
相关资源
最近更新 更多