2016-06-16 32 views
5

Vorrei unire più matrici insieme, prendendo la preferenza dei valori dal primo array e avendo solo valori univoci. C'è un modo più rapido rispetto all'utilizzo di array_merge(), array_unique() e l'operatore +?PHP array_merge() con preferenza solo del primo array e dei valori univoci?

function foo(...$params) { 
    $a = [ 
     'col1', 
     'col2_alias' => 'col2', 
     'col3' 
    ]; 
    $merged = array_merge($a, ...$params); 
    $unique = array_unique($merged); 
    print_r($merged); 
    print_r($unique); 
    print_r($a + $unique); 
} 

foo(
    ['col4', 'col5_alias' => 'col5', 'col6'], 
    ['col7', 'col1', 'col5_alias' => 'col5', 'col2_alias' => 'col10']); 

Proprio la fusione delle matrici mi dà valori duplicati, e sovrascrive i valori nel primo array:

Array 
(
    [0] => col1 // duplicate 
    [col2_alias] => col10 // overwritten 
    [1] => col3 
    [2] => col4 
    [col5_alias] => col5 
    [3] => col6 
    [4] => col7 
    [5] => col1 // duplicate 
) 

Utilizzando array_unique() risolve ovviamente i valori duplicati, ma non il valore sovrascritto:

Array 
(
    [0] => col1 
    [col2_alias] => col10 
    [1] => col3 
    [2] => col4 
    [col5_alias] => col5 
    [3] => col6 
    [4] => col7 
) 

Dopo aver utilizzato l'operatore +, l'array è come lo voglio.

+0

Vuoi prendere in considerazione utilizzando una libreria di raccolta? –

+1

Cosa c'è di male nell'operatore + se funziona correttamente? È lento? – instead

+0

@ ÁlvaroGuimarães Sfortunatamente, è in codice legacy e aggiungere una raccolta di raccolte sarebbe una seccatura. – GreeKatrina

risposta

0

È giusto presumere che l'utilizzo delle funzioni array_merge, array_unique e + sia lento. E ho scritto un po 'di codice per riferimento la velocità di ogni combinazione ...

qui è che il codice ...

<?php 

class ArraySpeeds 
{ 
    public $la = ['col1', 'col2_alias' => 'col2', 'col3']; 
    public $a = ['col4', 'col5_alias' => 'col5', 'col6']; 
    public $b = ['col7', 'col1', 'col5_alias' => 'col5', 'col2_alias' => 'col10']; 
    public $c = []; 

    public function executionTime ($callback) 
    { 
     $start = microtime (true); 

     for ($i = 0; $i < 1000000; $i++) { 
      $callback(); 
     } 

     return round ((microtime (true) - $start) * 1000) . '/ms' . PHP_EOL; 
    } 

    public function getTimes() 
    { 
     $array_merge_time = $this->executionTime (function() { 
      $this->c[0] = array_merge ($this->la, $this->a, $this->b); 
     }); 

     $array_unique_time = $this->executionTime (function() { 
      $merged = array_merge ($this->la, $this->a, $this->b); 
      $this->c[1] = array_unique ($merged); 
     }); 

     $addition_time = $this->executionTime (function() { 
      $merged = array_merge ($this->la, $this->a, $this->b); 
      $unique = array_unique ($merged); 
      $this->c[2] = $this->la + $unique; 
     }); 

     $array_diff_time = $this->executionTime (function() { 
      $merged = array_merge ($this->a, $this->b); 
      $diffed = array_diff ($merged, $this->la); 

      $this->c[3] = array_merge ($diffed, $this->la); 
     }); 

     echo print_r ($this->c[0], true), PHP_EOL; 
     echo print_r ($this->c[1], true), PHP_EOL; 
     echo print_r ($this->c[2], true), PHP_EOL; 

     natsort ($this->c[3]); 
     echo print_r ($this->c[3], true), PHP_EOL; 

     echo 'array_merge: ', $array_merge_time; 
     echo 'array_unique: ', $array_unique_time; 
     echo 'addition: ', $addition_time; 
     echo 'array_diff: ', $array_diff_time; 
    } 
} 

$arrayspeeds = new ArraySpeeds(); 
$arrayspeeds->getTimes(); 

Questa è l'uscita ...

Array 
(
    [0] => col1 
    [col2_alias] => col10 
    [1] => col3 
    [2] => col4 
    [col5_alias] => col5 
    [3] => col6 
    [4] => col7 
    [5] => col1 
) 

Array 
(
    [0] => col1 
    [col2_alias] => col10 
    [1] => col3 
    [2] => col4 
    [col5_alias] => col5 
    [3] => col6 
    [4] => col7 
) 

Array 
(
    [0] => col1 
    [col2_alias] => col2 
    [1] => col3 
    [2] => col4 
    [col5_alias] => col5 
    [3] => col6 
    [4] => col7 
) 

Array 
(
    [3] => col1 
    [col2_alias] => col2 
    [4] => col3 
    [0] => col4 
    [col5_alias] => col5 
    [1] => col6 
    [2] => col7 
) 

array_merge: 403/ms 
array_unique: 1039/ms 
addition: 1267/ms 
array_diff: 993/ms 

È possibile vedere che il tempo di esecuzione aumenta con ogni chiamata di funzione aggiunta, con le funzioni array_merge, array_unique e l'operatore + che è il più lento, più di due volte più lento.

Tuttavia, l'utilizzo di array_diff consente di ottenere prestazioni decenti con l'output corretto, ma senza un corretto ordinamento. L'aggiunta di una chiamata alla funzione natsort all'array lo risolverebbe.

Per esempio ...

function foo (...$params) 
{ 
    $a = [ 
     'col1', 
     'col2_alias' => 'col2', 
     'col3' 
    ]; 

    $diff = array_diff (array_merge (...$params), $a); 
    $merged = array_merge ($diff, $a); 
    natsort ($merged); 
    print_r ($merged); 
} 
+0

Non ho bisogno che vengano ordinati, quindi funziona perfettamente, grazie! – GreeKatrina

+0

Ho votato questa risposta, ma per qualche motivo mostra ancora zero. Se non hai ottenuto i punti rep, fallo sapere a SO. – GreeKatrina

1

In realtà non vedo alcun problema principale con il tuo script e non so perché vuoi migliorarlo. Ma ho scritto la mia implementazione della funzione e sembra che funziona un po 'più veloce, hanno uno sguardo (Ho anche aggiunto un paio di params per testare i risultati di funzione):

<?php 

function foo(...$params) { 
    $a = [ 
     'col1', 
     'col2_alias' => 'col2', 
     'col3' 
    ]; 
    $merged = array_merge($a, ...$params); 
    $unique = array_unique($merged); 

    return $a + $unique; 
} 

function foo2(...$params) { 
    $a = [ 
     'col1', 
     'col2_alias' => 'col2', 
     'col3' 
    ]; 
    $merged = array_merge(array_diff(array_merge(...$params), $a), $a); 

    return $merged; 
} 

$timeFoo = microtime(true); 
for($i = 0; $i < 1000000; $i++) { 
    foo(
    ['col13', 'col5_alias' => 'col3', 'col8'], 
    ['col21', 'col5_alias' => 'col1', 'col9'], 
    ['col4', 'col5_alias' => 'col5', 'col6'], 
    ['col7', 'col1', 'col5_alias' => 'col5', 'col2_alias' => 'col10']); 
} 
$timeFoo = microtime(true) - $timeFoo; 


$timeFoo2 = microtime(true); 
for($i = 0; $i < 1000000; $i++) { 
    foo2(
    ['col13', 'col5_alias' => 'col3', 'col8'], 
    ['col21', 'col5_alias' => 'col1', 'col9'], 
    ['col4', 'col5_alias' => 'col5', 'col6'], 
    ['col7', 'col1', 'col5_alias' => 'col5', 'col2_alias' => 'col10']); 
} 
$timeFoo2 = microtime(true) - $timeFoo2; 

echo "'foo' time: $timeFoo \n"; 
echo "'foo2' time: $timeFoo2 \n"; 

risultati differiscono da tempo a tempo, ma non così tanto:

'foo' time: 3.4310319423676 
'foo2' time: 2.5314350128174 

Quindi ci dà quasi il 30% di incremento delle prestazioni.