提问人:user8133761 提问时间:2/7/2020 最后编辑:mickmackusauser8133761 更新时间:2/8/2020 访问量:161
如何使用递归用户定义函数模拟 array_reverse()?
How to simulate array_reverse() using a recursive user-defined function?
问:
我想使用递归反转索引数组中的值。输出应与 array_reverse() 相同。
我的代码:
$array = [1,2,3,4,5,6,7];
function reverseString(&$s) {
if(count($s) < 2){
return;
}
$len = count($s);
$temp = $s[0];
$s[0] = $s[$len - 1];
$s[$len - 1] = $temp;
reverseString(array_slice($s, 1, $len - 2));
}
reverseString($array);
print_r($array);
返回:
Array (
[0] => 7
[1] => 2
[2] => 3
[3] => 4
[4] => 5
[5] => 6
[6] => 1 )
array_slice()
是数组部分的链接,对吗?
为什么内部元素不受我的递归交换技术的影响?
答:
5赞
arkascha
2/7/2020
#1
字符串和数组是两个独立的东西。我稍微清理了一下你的算法:
<?php
$array = [1,2,3,4,5,6,7];
function reverseSequence(&$s) {
$len = count($s);
if($len < 2){
return;
}
$rest = array_slice($s, 1, $len - 2);
reverseSequence($rest);
$s = array_merge([$s[$len - 1]], $rest, [$s[0]]);
}
reverseSequence($array);
print_r($array);
输出显然是:
Array
(
[0] => 7
[1] => 6
[2] => 5
[3] => 4
[4] => 3
[5] => 2
[6] => 1
)
1赞
mickmackusa
2/7/2020
#2
如果您打开了错误报告,您将看到以下三个通知:
注意:只有变量应该通过引用传递...
这是因为您将输出作为引用的参数传递;要解决此问题,您必须在传入之前将 'array_slice() 的输出声明为变量。array_slice()
您看到三个通知的事实实际上表明您的递归技术正在按预期遍历并执行工作,但生成的元素交换未应用于之前的调用 -- IOW 所有后续递归修改都将丢失。(演示$s
)
@arkascha比我早一个小时对你的脚本进行了必要的修复,但我的编写方式可能会略有不同。
代码:(演示)
function swapOutermost(&$a) {
$size = count($a);
if ($size > 1) {
$innerElements = array_slice($a, 1, -1);
swapOutermost($innerElements);
$a = array_merge(
[$a[$size - 1]], // last is put first
$innerElements, // recursed reference in the middle
[$a[0]] // first is put last
);
}
}
count()
每个递归调用只有一次 -- Arkascha 修复了这个问题- 没有写
return
-1
因为 的第 3 个参数与 .array_slice()
$len - 2
这是一种递归技术,它只使用迭代调用——没有切片或合并,因为它每次都传递整个原始输入数组。在递归过程中,只有目标索引会更改。我正在使用对称数组解构(PHP7.1 及更高版本提供的工具)基于索引增量进行交换。count()
代码:(演示)
function swapOutermost(&$a, $i = 0) {
$last = count($a) - 1 - $i;
if ($i < $last) {
[$a[$i], $a[$last]] = [$a[$last], $a[$i]];
swapOutermost($a, ++$i);
}
}
swapOutermost($array);
...当然,由于计数永远不会改变,因此只传入一次并重用它会更有效率。
function swapOutermost(&$a, $count, $i = 0) {
$last = $count - 1 - $i;
if ($i < $last) {
[$a[$i], $a[$last]] = [$a[$last], $a[$i]];
swapOutermost($a, $count, ++$i);
}
}
swapOutermost($array, count($array));
现在,您的原始代码片段使用引用修改,但您在问题要求中没有明确要求这样做 - 只是必须使用递归。如果你可能会接受一个递归函数来返回变量(因为,比如说,你希望能够将这个调用嵌套在另一个函数中),那么这里有一种方法可以在每个递归级别中传递一个越来越短的数组(就像你原来的一样):
代码:(演示)
function recursiveArrayReverse($a) {
$size = count($a);
if ($size < 2) {
return $a;
}
return array_merge(
[$a[$size - 1]],
recursiveArrayReverse(
array_slice($a, 1, -1)
),
[$a[0]]
);
}
$array = [1, 2, 3, 4, 5, 6, 7];
$array = recursiveArrayReverse($array);
评论
array_slice(...)
$array_slice(...)
$array_slice
array_slice