2009-09-10 9 views
15

Czy istnieje wbudowana funkcja dla PHP, aby sprawdzić, czy dwie tablice zawierają te same wartości (kolej nie ma znaczenia?).PHP: Wbudowana funkcja sprawdzania, czy dwie wartości Array są równe (Ignorowanie kolejności)

Na przykład, chcę funkcję zwracającą mnie prawdziwe w odniesieniu do dwóch następujących wejść:

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

Edit: Mógłbym klasyfikowane dwie tablice i porównać je, ale jak jestem taki leniwy facet , Wciąż wolałbym jeden liniowiec, który mogę wyciągnąć i użyć.

Odpowiedz

29

array_diff wygląda opcja:

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

lub jako oneliner w kodzie:

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

Możesz użyć 'pustego' tylko z varliables. – Gumbo

+0

gumbo: nie, możesz go używać na tablicach. zaczerpnięte z : "Następujące rzeczy są uważane za puste: # array() (pusta tablica)" – knittl

+3

Gumbo ma rację. Nie możesz użyć wartości zwracanej przez funkcję za pomocą 'empty'. Tak właśnie mówił. Musisz zapisać zwracaną wartość 'array_diff' w zmiennej temp lub po prostu użyć operatora nie:' return! Array_diff ($ a1, $ a2) '. –

7

Najlepszym rozwiązaniem jest, aby uporządkować zarówno tablicę, a następnie porównać je:

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

Jako funkcję:

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

Oto kolejny algorytm szuka każdego elementu czy to w 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; 
} 

Ale to ma złożoność O (n^2). Więc lepiej skorzystaj z metody sortowania.

+0

ponieważ jestem takim leniwym facetem, nadal wolałbym jeden liniowiec, który mogę wyciągnąć i użyć. – Graviton

+2

@Ngu Soon Hui - tak owinąć kod Gumbo w funkcję (array_equals ($ arr1, $ arr2))? – karim79

+2

Byłoby pomocne, gdyby osoba, która głosowała, skomentowała, dlaczego głosował na moją odpowiedź. – Gumbo

2

Można użyć 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 
} 

Jednak problem z tym podejściem polega na tym, że tablice mogą zawierać zduplikowane elementy i nadal pasują do siebie.

+1

Ktoś wie szczegóły różnicy wydajności między diff i sortowania w php? – Kazar

+2

'jeśli (array_diff ($ a, $ b)) {}' zrobiłby. pusta tablica ocenia na false. – SilentGhost

+0

Użycie 'array_diff' jest łatwe. Ale wymaga dodatkowej przestrzeni (O (* n *)), ponieważ tworzona jest dodatkowa tablica, w której przechowywane są te elementy * A *, które nie są również elementem * B *. – Gumbo

3

array_diff() powyżej metoda nie zadziała. Instrukcja

php.net mówi, że array_diff() to robi „Zwraca tablicę zawierającą wszystkie wpisy z tablica1 które nie są obecne w żadnym z innych tablic”

więc rzeczywista metoda array_diff() byłoby:

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

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

jednak pójdę metodą sortowania: D

+0

+1 to lepszy sposób na zrobienie tego . Znalazłem ten problem dzisiaj i skończyło się na używaniu '! Array_diff ($ a, $ b) &&! Array_diff ($ b, $ a)'. Nie jest to najlepsze rozwiązanie, ale działa. – Weboide

+0

Uwaga boczna: Mimo że jest to kwestia OP, warto pamiętać, że użycie 'array_diff()' (i podobnych, takich jak 'array_intersect()') będzie nieudane na tablicach wielowymiarowych ** (PHP notice: _Array na ciąg konwersji_), przy użyciu prostych operatorów tablic z '==' i '===' będzie działał na takich tablicach bez żadnych problemów. – trejder

0

Można użyć array_intersect() zamiast 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))); 

Wydajność mądry. rozwiązanie, w którym dwa czynniki są ważne:

  • tym częściej tablice są dopasowane, tym bardziej array_intersect() jest szybki.
  • im więcej tablic jest dużych (więcej niż 10 wartości), tym bardziej array_intersect() jest szybka.

W zależności od tych czynników jedna metoda może być dwa lub trzy razy szybsza od drugiej. W przypadku dużych tablic z kilkoma (lub nie) pasującymi kombinacjami lub małych tablic z dużą liczbą dopasowań obie metody są równoważne.

Jednak metoda sortowania jest zawsze szybsza, z wyjątkiem przypadku małych tablic z niewielkimi lub żadnymi pasującymi kombinacjami. W tym przypadku metoda array_diff() jest o 30% szybsza.

+0

Uwaga dotycząca formatowania: Użyłeś źle napisanego kodu HTML zamiast Markdown (poprawiono) i wydaje się, że nie lubisz dużych liter na początku każdej sekcji (ustalone). Ogólnie rzecz biorąc, powinienem poprzestać na lenistwie! :] Ale, z drugiej strony, dostarczyłeś wyjątkową i interesującą odpowiedź, więc wszystko w porządku! :] – trejder

1

Należy porównać tylko jednokierunkowe przy użyciu array_diff() i użyć count() dla odwróconej relacji.

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

Jeżeli macierze porównywanych składać się tylko ciągi i/lub liczb, array_count_values pozwala porównać tablice szybko (w O(n) czasie vs O(n log n) do sortowania), weryfikując, że obie tablice zawierają te same wartości i że każda wartość występuje w obu tablicach tyle samo razy.

if(array_count_values($a1) == array_count_values($a2)) { 
    //arrays are equal 
} 
Powiązane problemy