2009-05-21 19 views
16

तो $ सरणी एक सरणी है जिसमें सभी तत्व संदर्भ हैं।संदर्भों के PHP सरणी की गहरी प्रति

मैं इस सरणी को $ परिणामों (लूप में) नामक किसी अन्य सरणी में जोड़ना चाहता हूं, लेकिन चूंकि वे संदर्भ हैं, PHP संदर्भों की प्रतिलिपि बनाता है और $ परिणाम समान तत्वों से भरे हुए हैं।

अब तक सबसे अच्छा काम कर समाधान है:

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

जो मुझे डर है अविश्वसनीय रूप से अक्षम होने के लिए। क्या ऐसा करने के लिए इससे अच्छा तरीका है?

+0

@leonbloy मैं सहमत हूं। – Chad

उत्तर

9

आप तथ्य यह है कि कार्यों dereferences परिणाम जब, लौटने उदाहरण के लिए उपयोग कर सकते हैं यहाँ $array_by_myclone अभी भी $original ($array_by_myclone[0][0] == 'foo') के लिए एक संदर्भ होगा जबकि $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      

संपादित एक क्लोन मूल्य होगा: मैं यह जांचना चाहता था कि unserialize(serialize()) कहने वाली टिप्पणी तेज थी, इसलिए मैंने PHP 5.5 का उपयोग करके परीक्षण किया था, और यह पता चला है कि यह गलत है: serialization विधि का उपयोग करके छोटे डेटासेट के साथ भी धीमा है, और जितना अधिक डेटा आपके पास धीमा है हो जाता है।

[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 

कोड का प्रयोग किया:

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

मैंने थोड़ा बेंचमार्किंग और unserialize (serialize()) थोड़ा तेज किया है – Chad

+1

+1 दिलचस्प तथ्य, हालांकि। – fresskoma

+4

यह बेहद संदिग्ध है कि धारावाहिक array_map से तेज़ है। हो सकता है कि यदि आपका सरणी केवल एक तत्व है जो कुछ वर्ण लंबा है। –

0

serialize कारण array_map साथ array_map तुलना करने के लिए कोई जरूरत नहीं उपयोगी नहीं है।

$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 दिए गए सरणी के तत्वों को कॉलबैक लागू करता है, जैसे कि foreach। यदि आप जिस सरणी को कॉपी करना चाहते हैं, उसके पास 1 से अधिक घोंसला है, array_map काम नहीं करता है।

संबंधित मुद्दे