繁体   English   中英

如何使用递归用户定义函数模拟 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()是数组部分的链接,对吗?

为什么内部元素不受我的递归交换技术的影响?

字符串和数组是两个不同的东西。 我稍微澄清了你的算法:

<?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
)

如果您打开了错误报告,您将看到以下三个通知:

注意:只有变量应该通过引用传递...

这是因为您将array_slice()的输出作为引用参数传递; 要解决此问题,您必须在传入之前将 `array_slice() 的输出声明为变量。

您看到三个通知的事实实际上表明您的递归技术按预期遍历并完成工作,但结果元素交换并未应用于$s上的先前调用 - IOW 所有随后的递归修改丢失了。 演示


@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作为array_slice()的第三个参数与$len - 2具有相同的效果。

这是一种仅使用迭代count()调用的递归技术——没有切片或合并,因为它每次都传递整个原始输入数组。 只有目标索引在递归过程中发生变化。 我正在使用 对称数组解构PHP7.1 及更高版本提供的工具)基于索引增量进行交换。

代码:(演示

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);

暂无
暂无

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

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