我在 php 中玩了一下递归。不幸的是,php 值智能复制想法和默认通过引用传递对象并没有使它更容易。出现问题是因为迭代编号 X 所做的修改在迭代 ex X-2 中可见
例如:
/**
* Silly function to find last element in array
* @param ArrayObject $input
*/
function process(ArrayObject $input) {
if ($input->count() == 1) {
return $input->getIterator()->current();
}
$ar = $input->getArrayCopy();
array_shift($ar);
$input->exchangeArray($ar);
return process($input);
}
$in = new ArrayObject(range('a', 'd'));
echo 'Before ' . PHP_EOL;
var_dump($in);
echo PHP_EOL . 'Process - last element is: ' . process($in) . PHP_EOL;
echo 'After ' . PHP_EOL;
var_dump($in);
输出是
Before
object(ArrayObject)#1 (1) {
["storage":"ArrayObject":private]=>
array(4) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "c"
[3]=>
string(1) "d"
}
}
Process - last element is: d
After
object(ArrayObject)#1 (1) {
["storage":"ArrayObject":private]=>
array(1) {
[0]=>
string(1) "d"
}
}
正如您所见,递归也修改了原始 $in 变量,我期望每次新迭代都将对值的副本进行操作。在这个例子中它不是必需的,但是如果递归函数更复杂的话。
简单的解决方案 - 克隆
function process(ArrayObject $input) {
$input = clone ($input);
if ($input->count() == 1) {
return $input->getIterator()->current();
}
$ar = $input->getArrayCopy();
array_shift($ar);
$input->exchangeArray($ar);
return process($input);
}
好的,可以,但是如果输入是非常复杂的多对象嵌套循环结构怎么办?好的,那么我可以序列化和反序列化值作为深拷贝的替代品
function process(ArrayObject $input) {
$input = unserialize(serialize($input));
if ($input->count() == 1) {
return $input->getIterator()->current();
}
$ar = $input->getArrayCopy();
array_shift($ar);
$input->exchangeArray($ar);
return process($input);
}
完美 - 它可以工作,但是在每次迭代中取消/序列化(尤其是使用巨大的 $ 输入)有点浪费时间和 cpu。
有没有其他方法可以做到这一点,这让我不必担心我需要“破解一点”才能使用 php 进行标准用法。
//编辑带有 Tigrang 建议的示例
Tigrang 你的建议很有趣,但是
function process(ArrayObject $input) {
$input = new ArrayObject(($input));
$input->offsetSet(null, 'f');
}
$in = new ArrayObject(range('a', 'd'));
echo 'Before ' . PHP_EOL;
var_dump($in);
process($in);
echo 'After ' . PHP_EOL;
var_dump($in);
After
object(ArrayObject)#1 (1) {
["storage":"ArrayObject":private]=>
array(5) {
[0]=>
string(1) "a"
[1]=>
string(1) "b"
[2]=>
string(1) "c"
[3]=>
string(1) "d"
[4]=>
string(1) "f"
}
}
它仍然保持对外部变量的引用
//编辑 2
class Engine {
public $power = 999;
}
class Car {
public $name = '';
public $engine = '';
public function __construct($name, $power) {
$this->name = $name;
$this->engine = new Engine();
$this->engine->power = $power;
}
}
function process(ArrayObject $input) {
$input = new ArrayObject(($input->getArrayCopy()));
$ford = $input[0];
$ford->name = 'Audi';
$ford->engine->power = 1500;
}
$ar = array(new Car('Ford', 130));
$in = new ArrayObject($ar);
echo 'Before ' . PHP_EOL;
var_dump($in);
process($in);
echo 'After ' . PHP_EOL;
var_dump($in);