2009-09-10 16 views
15

Esiste una funzione integrata per PHP che consente di verificare se due array contengono gli stessi valori (ordine non importante?).PHP: Funzione integrata per verificare se due valori di matrice sono uguali (Ignorare l'ordine)

Ad esempio, voglio una funzione che restituisce mi vero per i due ingressi:

array('4','5','2') 
array('2','4','5') 

Edit: avrei potuto ordinato due array e confrontarli, ma come io sono un ragazzo pigro , Preferirei comunque un one-liner che posso estrarre e utilizzare.

risposta

29

array_diff si presenta come un'opzione:

function array_equal($a1, $a2) { 
    return !array_diff($a1, $a2) && !array_diff($a2, $a1); 
} 

o come oneliner nel codice:

if(!array_diff($a1, $a2) && !array_diff($a2, $a1)) doSomething(); 
+3

Puoi usare 'vuoto' solo con variabili. – Gumbo

+0

gumbo: no, puoi usarlo sugli array bene. tratto da : "Le seguenti cose sono considerate vuote: # array() (un array vuoto)" – knittl

+3

Gumbo ha ragione. Non è possibile utilizzare il valore di ritorno di una funzione con 'empty'. Questo è quello che stava effettivamente dicendo. Devi memorizzare il valore di ritorno di 'array_diff' in una variabile temporanea o semplicemente usare l'operatore not:' return! Array_diff ($ a1, $ a2) '. –

7

La soluzione migliore è di ordinare sia matrice e poi confrontarli:

$a = array('4','5','2'); 
$b = array('2','4','5'); 
sort($a); 
sort($b); 
var_dump($a === $b); 

In funzione:

function array_equal($a, $b, $strict=false) { 
    if (count($a) !== count($b)) { 
     return false; 
    } 
    sort($a); 
    sort($b); 
    return ($strict && $a === $b) || $a == $b; 
} 

Ecco un altro algoritmo ricerca di ogni elemento di A se è in B:

function array_equal($a, $b, $strict=false) { 
    if (count($a) !== count($b)) { 
     return false; 
    } 
    foreach ($a as $val) { 
     $key = array_search($val, $b, $strict); 
     if ($key === false) { 
      return false; 
     } 
     unset($b[$key]); 
    } 
    return true; 
} 

Ma questo ha una complessità di O (n^2). Quindi è meglio usare il metodo di smistamento.

+0

come io sono un ragazzo pigro, io allo stesso tempo di una battuta che posso tirare fuori e utilizzare. – Graviton

+2

@Ngu Soon Hui - quindi avvolgi il codice di Gumbo in una funzione (array_equals ($ arr1, $ arr2))? – karim79

+2

Sarebbe utile se il down-voter commentasse perché ha votato la mia risposta. – Gumbo

2

È possibile utilizzare array_diff.

$a = array('4','5','2'); 
$b = array('2','4','5'); 

if(count(array_diff($a, $b)) == 0) { 
    // arrays contain the same elements 
} else { 
    // arrays contain different elements 
} 

Tuttavia, un problema con questo approccio è che gli array possono contenere elementi duplicati e corrispondono ancora.

+1

Qualcuno conosce i dettagli sulla differenza di prestazioni tra un diff e un ordinamento in php? – Kazar

+2

'if (array_diff ($ a, $ b)) {}' farebbe. array vuoto da valutare su false. – SilentGhost

+0

L'uso di 'array_diff' è facile. Ma richiede uno spazio extra (O (* n *)) poiché viene creato un array addizionale dove sono memorizzati quegli elementi di * A *, che non sono anche elementi di * B *. – Gumbo

3

Il metodo array_diff() di cui sopra non funzionerà. manuale

di php.net dice che array_diff() fa questo:

"restituisce un array contenente tutte le voci di array1 che non sono presenti in nessuna delle altre matrici."

Così il metodo effettivo array_diff() sarebbe:

function array_equal($array1, $array2) 
{ 
    $diff1 = array_diff($array1, $array2); 
    $diff2 = array_diff($array2, $array1); 

    return 
    (
     (count($diff1) === 0) && 
     (count($diff2) === 0) 
    ); 
} 

Comunque vado con l'ordine: D

+0

+1 questo è un modo migliore per farlo . Oggi ho trovato il problema e ho finito con l'uso di '! Array_diff ($ a, $ b) &&! Array_diff ($ b, $ a)'. Non è la soluzione migliore, ma funziona. – Weboide

+0

Una nota a margine: se, questo è fuori discussione del PO, vale la pena ricordare, che l'uso di 'array_diff()' (e simile come 'array_intersect()') avrà ** fallire su multidimensionale array ** (avviso PHP: _Array to string conversion_), mentre l'uso di operatori di array semplici di '==' e '===' funzionerà su tali array senza problemi. – trejder

0

È possibile utilizzare array_intersect() invece di array_diff():

$a = array('4','5','2'); 
$b = array('2','4','5'); 
$ca = count($a); 
$cb = count($b); 
$array_equal = ($ca == $cb && $ca == count(array_intersect($a, $b))); 

prestazioni saggio. soluzione, dove due fattori sono importanti:

  • più spesso array sono corrispondenti, più array_intersect() è veloce.
  • più array sono grandi (più di 10 valori), più array_intersect() è veloce.

In base a questi fattori, un metodo può essere due o tre volte più veloce dell'altro. Per i grandi array con poche (o nessuna) combinazioni di corrispondenza, o per piccoli array con un sacco di corrispondenza, entrambi i metodi sono equivalenti.

Tuttavia, il metodo di ordinamento è sempre più veloce, tranne nel caso di piccoli array con poche o nessuna combinazione di corrispondenza. In questo caso il metodo array_diff() è più veloce del 30%.

+0

Avviso di formattazione: hai usato HTML scritto male invece di Markdown (corretto) e sembra che non ti piacciano le lettere maiuscole all'inizio di ogni sezione (fisso). Quindi, in generale, dovrei minimizzare la tua pigrizia! :] Ma, d'altra parte, hai fornito una risposta eccezionale e interessante, quindi va bene! :] – trejder

1

È necessario solo confrontare a senso unico utilizzando array_diff() e utilizzare count() per la relazione invertita.

if (count($a1) == count($a2) && !array_diff($a1, $a2)) { 
    // equal arrays 
} 
0

Se gli array a confronto consistere solo stringhe e/o interi, array_count_values ti permette di confrontare le matrici rapidamente (in O(n) tempo vs O(n log n) per l'ordinamento) verificando che entrambi gli array contengono gli stessi valori e che ogni il valore si verifica lo stesso numero di volte in entrambi gli array.

if(array_count_values($a1) == array_count_values($a2)) { 
    //arrays are equal 
} 
Problemi correlati