Deep copy of PHP array of references

前端 未结 2 1354
温柔的废话
温柔的废话 2020-12-06 16:32

So $array is an array of which all elements are references.

I want to append this array to another array called $results (in a loop), but since they are references,

相关标签:
2条回答
  • 2020-12-06 16:56

    You can use the fact that functions dereferences results when returning, for exemple here $array_by_myclone will still have a reference to $original ($array_by_myclone[0][0] == 'foo') while $array_by_assignment will have a cloned value ($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                     
    

    EDIT: I wanted to check if the comment saying unserialize(serialize()) was faster was right so I did the test using php 5.5, and it turns out this is wrong: using the serialization method is slower even with a small dataset, and the more data you have the slower it gets.

    lepidosteus@server:~$ 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
    lepidosteus@server:~$ php reference.php 1
    myclone:   0.000010 seconds
    serialize: 0.000012 seconds
    lepidosteus@server:~$ php reference.php 1000000
    myclone:   0.398540 seconds
    serialize: 0.706631 seconds
    

    Code used:

    <?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);
    
    0 讨论(0)
  • 2020-12-06 17:07

    no need to compare array_map with serialize cause array_map is not useful.

    $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 Applies the callback to the elements of the given arrays, just like foreach. if the array you want to copy has more than 1 nest, array_map does not work.

    0 讨论(0)
提交回复
热议问题