我在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(特别是使用巨大的$ input)。
有没有其他方法可以做到这一点,让我不必担心我需要'破解'使用php进行标准使用。
// TIGNng建议的编辑示例
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);
答案 0 :(得分:3)
AFAIK,这是PHP的限制。正如你所指出的那样,这是因为PHP 5x中的两件事并不是免费的。
unserialize(serialize($obj)
是目前唯一可用的(非常低效)解决方案。让我们希望众神能够在即将到来的版本中解决其中的一些问题,而不是仅仅打破如何在大肆宣传(延迟)的版本6中实现unicode!
答案 1 :(得分:0)
为什么不$input = new ArrayObject($input);
据我所知,它是深层嵌套的复制品,比序列化更快:http://viper-7.com/kHLCCP