2009-05-21 23 views
16

$ dizisi, tüm öğelerin referans aldığı bir dizidir.PHP dizi başvuru dizisinin kopya kopyası

Bu diziyi $ results (bir döngüde) adı verilen başka bir diziye eklemek istiyorum, ancak başvurular olduklarından, PHP başvuruları kopyalar ve $ sonuçları aynı öğelerle doludur.

Şimdiye kadar, iyi çalışma çözümdür: Korkarım

$results[] = unserialize(serialize($array)); 

inanılmaz verimsiz olması. Bunu yapmanın daha iyi bir yolu var mı?

+0

@leonbloy Katılıyorum. – Chad

cevap

9

$array_by_assignment ($array_by_assignment[0][0] == 'bar')

$original = 'foo'; 
$array_of_reference = array(&$original); 

function myclone($value) 
{ 
    return $value; 
} 

$array_by_myclone = array(); 
$array_by_myclone[] = array_map('myclone', $array_of_reference); 

$array_by_assignment = array(); 
$array_by_assignment[] = $array_of_reference; 

$original = 'bar'; 

var_dump($array_by_myclone[0][0]); // foo, values were cloned                                 
var_dump($array_by_assignment[0][0]); // bar, still a reference      

DÜZENLEME bir klonlanmış değere sahip olurken Burada $array_by_myclone hala $original ($array_by_myclone[0][0] == 'foo') bir başvuru olacak işlevler dereferences sonuçları Exemple için, dönen gerçeğini kullanabilirsiniz: Ben unserialize(serialize()) yorumunun daha hızlı olduğunu kontrol etmek istedim, bu yüzden php 5.5 kullanarak testi yaptım ve bunun yanlış olduğu ortaya çıktı: seri hale getirme yönteminin kullanılması küçük bir veri kümesinde bile daha yavaş ve daha yavaş veri var. alır. kullanılan

[email protected]:~$ php -v 
PHP 5.5.1-1~dotdeb.1 (cli) (built: Aug 3 2013 22:19:30) 
Copyright (c) 1997-2013 The PHP Group 
Zend Engine v2.5.0, Copyright (c) 1998-2013 Zend Technologies 
    with Zend OPcache v7.0.2-dev, Copyright (c) 1999-2013, by Zend Technologies 
[email protected]:~$ php reference.php 1 
myclone: 0.000010 seconds 
serialize: 0.000012 seconds 
[email protected]:~$ php reference.php 1000000 
myclone: 0.398540 seconds 
serialize: 0.706631 seconds 

Kodu:

<?php 
$iterations = 1000000; 
if (isset($argv[1]) && is_numeric($argv[1])) { 
    $iterations = max(1, (int)$argv[1]); 
} 

$items = array(); 
for ($i = 0; $i < $iterations; $i++) { 
    $items[] = 'item number '.$i; 
} 

$array_of_refs = array(); 
foreach ($items as $k => $v) { 
    $array_of_refs[] = &$items[$k]; 
} 

function myclone($value) 
{ 
    return $value; 
} 

$start = microtime(true); 

$copy = array_map('myclone', $array_of_refs); 

$time = microtime(true) - $start; 

printf("%-10s %2.6f seconds\n", 'myclone:', $time); 

$start = microtime(true); 

$copy = unserialize(serialize($array_of_refs)); 

$time = microtime(true) - $start; 

printf("%-10s %2.6f seconds\n", 'serialize:', $time); 
+7

Ben biraz kıyaslama ve kararsızlaştırdı (serialize()) biraz daha hızlı – Chad

+1

+1 İlginç olsa da. – fresskoma

+4

Seri hale getirmenin array_map'ten daha hızlı olduğu şüpheli. Belki de diziniz sadece birkaç karakter uzunluğunda olan bir elementse. –

0

serialize neden array_map ile array_map karşılaştırmak gerek kullanışlı değildir.

$original = array('key'=>'foo'); 
$array_of_reference = array(&$original); 
function myclone($value) 
{ 
    return $value; 
} 
$array_by_myclone = array(); 
$array_by_myclone[] = array_map('myclone', $array_of_reference); 

$array_by_assignment = array(); 
$array_by_assignment[] = $array_of_reference; 

$original['key'] = 'bar'; 

var_dump($array_by_myclone[0][0]['key']); // bar, still a reference                                 
var_dump($array_by_assignment[0][0]['key']); // bar, still a reference 

array_map Geri çağırma ifadesini, verilen dizinin öğelerine, foreach gibi uygular. Kopyalamak istediğiniz dizi 1'den fazla yuva içeriyorsa, array_map çalışmıyor.