PHP - Sprawdź, czy dwie tablice są równe

280

Chciałbym sprawdzić, czy dwie tablice są równe. Mam na myśli: ten sam rozmiar, ten sam indeks, te same wartości. Jak mogę to zrobić?

Używając !==zgodnie z sugestią użytkownika, spodziewam się, że następujące polecenie wypisze polecenie enter, jeśli co najmniej jeden element w tablicy (ach) jest inny, ale w rzeczywistości tak nie jest.

if (($_POST['atlOriginal'] !== $oldAtlPosition) 
    or ($_POST['atl'] !== $aext) 
    or ($_POST['sidesOriginal'] !== $oldSidePosition) 
    or ($_POST['sidesOriginal'] !== $sideext)) {

    echo "enter";
}
markzzz
źródło
17
Używasz =zbyt dużo, powinno być !==albo!=
Jeroen
29
Dla przypomnienia (ponieważ moja edycja została zmieniona z powrotem na „użytkownika”) jest to „użytkownik”: english.stackexchange.com/questions/105116/…
teynon
7
['a'] == [0]jest true. To tylko PHP.
Dávid Horváth,
2
@ DávidHorváth to naprawdę dziwne, dobrą praktyką jest zawsze używać ===
AFA z
1
@ DávidHorváth, luźne porównanie jest luźne nie tylko w PHP. Jeśli spojrzysz na JS, będziesz zaskoczony. Po prostu nie używaj, dopóki nie zrozumiesz lepiej.
ryabenko-pro

Odpowiedzi:

508
$arraysAreEqual = ($a == $b); // TRUE if $a and $b have the same key/value pairs.
$arraysAreEqual = ($a === $b); // TRUE if $a and $b have the same key/value pairs in the same order and of the same types.

Zobacz Operatory macierzy .

EDYTOWAĆ

Operator nierówności polega na tym !=, że operator braku tożsamości ma !==dopasować operator równości ==i operator tożsamości ===.

Stefan Gehrig
źródło
79
Uwaga dodatkowa: To podejście działa również w przypadku tablic wielowymiarowych (wcześniej nie było to dla mnie oczywiste).
trejder
5
PS: rozwiązaniem jest użycie array_values($a)==array_values($b)... Kolejnym typowym problemem są unikalne wartości, więc pamiętaj, że istnieją array_unique().
Peter Krauss
13
Ta odpowiedź jest zła. ==działa niezależnie od kolejności tylko dla typowych słowników takich jak [1 => 'a', 2 => 'b']. Dla np [1 => 'a', 2 => 'b'] == [2 => 'b', 1 => 'a']. W przypadku indeksowanych tablic, jak ['a', 'b'] ==nie działa, jak podano. Dla np ['a', 'b'] != ['b', 'a'].
nawfal
37
@nawfal: Twoje założenie jest błędne. ['a', 'b']jest tablicą [0 => 'a', 1 => 'b'], podczas gdy ['b', 'a']jest tablicą [0 => 'b', 1 => 'a']. Dlatego nie mają takich samych par klucz / wartość, jak podano w mojej odpowiedzi i dlatego ==nie działa między nimi.
Stefan Gehrig
29
@StefanGehrig oh masz rację. Zostawię swój komentarz jako taki, aby moja głupota
stała się
88

Według tej strony .

UWAGA: Akceptowana odpowiedź działa dla tablic asocjacyjnych, ale nie będzie działać zgodnie z oczekiwaniami w przypadku tablic indeksowanych (wyjaśnione poniżej). Jeśli chcesz porównać jedno z nich, skorzystaj z tego rozwiązania. Ponadto ta funkcja może nie działać z tablicami wielowymiarowymi (ze względu na naturę funkcji array_diff).

Testowanie dwóch indeksowanych tablic, których elementy są w innej kolejności, przy użyciu $a == $blub $a === $bniepowodzenia, na przykład:

<?php
    (array("x","y") == array("y","x")) === false;
?>

Jest tak, ponieważ powyższe oznacza:

array(0 => "x", 1 => "y")vs array(0 => "y", 1 => "x").

Aby rozwiązać ten problem, użyj:

<?php
function array_equal($a, $b) {
    return (
         is_array($a) 
         && is_array($b) 
         && count($a) == count($b) 
         && array_diff($a, $b) === array_diff($b, $a)
    );
}
?>

Dodano porównywanie rozmiarów tablic (sugerowane przez super_ton), ponieważ może to poprawić prędkość.

lepe
źródło
2
Uwaga: nie działa zgodnie z oczekiwaniami w przypadku tablic wielowymiarowych
maersu
8
Powyższy komentarz jest fałszywy. Jeśli $ b ma wszystkie elementy $ a ma plus kilka dodatkowych, dwie tablice nie są równe, ale powyższy kod powie, że są.
Ghola
1
warto dodać również count ($ a) == count ($ b)
stefan
1
@ super_ton: tak, przed wywołaniem array_diffmoże przyspieszyć porównanie. Dodam to. Dzięki
lepe
3
Niestety w niektórych przypadkach nie działa, na przykład przetestowałem następującą skrzynkę $a = [1, 2, 2]; $b = [2, 1, 1];i powróciło true, ale dwie tablice oczywiście nie są takie same.
AwesomeGuy
33

Spróbuj serializować. Spowoduje to również sprawdzenie zagnieżdżonych podstron.

$foo =serialize($array_foo);
$bar =serialize($array_bar);
if ($foo == $bar) echo "Foo and bar are equal";
Iggi
źródło
7
Problematyczne, jeśli klucze i wartości są przesuwane tak, jak przy użyciu porównania. Jednak zakładając, że oczekuje się, że będą w 100% takie same, jest to najczystszy i najłatwiejszy sposób sprawdzenia głębokiej równości!
Kevin Peno
1
Myślę, że to najlepsze rozwiązanie! Może porównać tablice wielowymiarowe i asocjacyjne, jeśli zostały wcześniej posortowane!
Rafael Moni
13

Krótkie rozwiązanie, które działa nawet z tablicami, których klucze są podawane w innej kolejności:

public static function arrays_are_equal($array1, $array2)
{
    array_multisort($array1);
    array_multisort($array2);
    return ( serialize($array1) === serialize($array2) );
}
Samuel Vicent
źródło
3
Prawdopodobnie najlepsza jak dotąd odpowiedź, większość odpowiedzi albo nie pasuje, jeśli klawisze są przesunięte lub jeśli jest to tablica wielowymiarowa.
AwesomeGuy,
11

Porównaj je z innymi wartościami:

if($array_a == $array_b) {
  //they are the same
}

Możesz przeczytać o wszystkich operatorach tablic tutaj: http://php.net/manual/en/language.operators.array.php Uwaga, na przykład, że ===sprawdza również, czy typy i kolejność elementów w tablicach są takie same.

Emil Vikström
źródło
5
Lub w ===zależności od pożądanego zachowania.
Matthew Flaschen
9

!===nie będzie działać, ponieważ jest to błąd składniowy. Prawidłowy sposób to !==(nie trzy symbole „równe”)

Sodhi Saab
źródło
5
if (array_diff($a,$b) == array_diff($b,$a)) {
  // Equals
}

if (array_diff($a,$b) != array_diff($b,$a)) {
  // Not Equals
}

Z mojego pov lepiej jest użyć array_diff niż array_intersect, ponieważ przy sprawdzeniach tego rodzaju różnice zwykle zwracane są mniejsze niż podobieństwa, w ten sposób konwersja bool jest mniej wymagająca pamięci.

Edytuj Zauważ, że to rozwiązanie jest dla prostych tablic i uzupełnia powyższe == i ===, które jest ważne tylko dla słowników.

Marcos Fernandez Ramos
źródło
4

array_diff - Oblicza różnicę tablic

http://php.net/manual/en/function.array-diff.php

array array_diff ( array $array1 , array $array2 [, array $... ] )

Porównuje array1z jedną lub większą liczbą innych tablic i zwraca wartości array1, które nie występują w żadnej z innych tablic.

Scherbius.com
źródło
4
OP chce „sprawdzić, czy dwie tablice są równe”. array_diffnie mogę ci tego powiedzieć. Spróbować array_diff([1, 2], [1, 2, 'hello']).
marcv
3

Inna metoda sprawdzania równości bez względu na kolejność wartości działa przy użyciu http://php.net/manual/en/function.array-intersect.php , na przykład:

$array1 = array(2,5,3);
$array2 = array(5,2,3);
if($array1 === array_intersect($array1, $array2) && $array2 === array_intersect($array2, $array1)) {
    echo 'Equal';
} else {
    echo 'Not equal';
}

Oto wersja, która działa również z tablicami wielowymiarowymi przy użyciu http://php.net/manual/en/function.array-uintersect.php :

$array1 = array(
    array(5, 2),
    array(3, 6),
    array(2, 9, 4)
);
$array2 = array(
    array(3, 6),
    array(2, 9, 4),
    array(5, 2)
);

if($array1 === array_uintersect($array1, $array2, 'compare') && $array2 === array_uintersect($array2, $array1, 'compare')) {
    echo 'Equal';
} else {
    echo 'Not equal';
}

function compare($v1, $v2) {
    if ($v1===$v2) {
        return 0;
    }
    if ($v1 > $v2) return 1;
    return -1;
}
białybrow
źródło
3
function compareIsEqualArray(array $array1,array $array):bool
{

   return array_diff($array1,$array2)==[];

}
dılo sürücü
źródło
2
Pomocne jest wyjaśnienie, co robi przykładowy kod. Czy działa to również w przypadku tablic wielowymiarowych?
k0pernikus
1
array_diff pobierz inny element z tablicy, jeśli array_diff zwróci pustą tablicę dwie tablice są równe
dılo sürücü
2

Jeden sposób: (wdrożenie „uważane za równe” dla http://tools.ietf.org/html/rfc6902#section-4.6 )

W ten sposób tablice asocjacyjne, których członkowie są uporządkowane inaczej - np. Będą uważane za równe w każdym języku oprócz php :)

// recursive ksort
function rksort($a) {
  if (!is_array($a)) {
    return $a;
  }
  foreach (array_keys($a) as $key) {
    $a[$key] = ksort($a[$key]);
  }
  // SORT_STRING seems required, as otherwise
  // numeric indices (e.g. "0") aren't sorted.
  ksort($a, SORT_STRING);
  return $a;
}


// Per http://tools.ietf.org/html/rfc6902#section-4.6
function considered_equal($a1, $a2) {
  return json_encode(rksort($a1)) === json_encode(rksort($a2));
}
Mike McCabe
źródło
1
Uważam, że powinno być:$a[$key] = rksort($a[$key]);
pinkeen
2

Problem ze składnią twoich tablic

$array1 = array(
    'a' => 'value1',
    'b' => 'value2',
    'c' => 'value3',
 );

$array2 = array(
    'a' => 'value1',
    'b' => 'value2',
    'c' => 'value3',
 );

$diff = array_diff($array1, $array2);

var_dump($diff); 
YEFFOU WAGOUM THIERRY HENRI
źródło
2

Oto przykład, jak porównać do tablic i uzyskać różnicę między nimi.

$array1 = ['1' => 'XXX', 'second' => [
            'a' => ['test' => '2'],
            'b' => 'test'
        ], 'b' => ['no test']];

        $array2 = [
            '1' => 'XX',
            'second' => [
                'a' => ['test' => '5', 'z' => 5],
                'b' => 'test'
            ],
            'test'
        ];


        function compareArrayValues($arrayOne, $arrayTwo, &$diff = [], $reversed = false)
        {
            foreach ($arrayOne as $key => $val) {
                if (!isset($arrayTwo[$key])) {
                    $diff[$key] = 'MISSING IN ' . ($reversed ? 'FIRST' : 'SECOND');
                } else if (is_array($val) && (json_encode($arrayOne[$key]) !== json_encode($arrayTwo[$key]))) {
                    compareArrayValues($arrayOne[$key], $arrayTwo[$key], $diff[$key], $reversed);
                } else if ($arrayOne[$key] !== $arrayTwo[$key]) {
                    $diff[$key] = 'DIFFERENT';
                }
            }
        }

        $diff = [];
        $diffSecond = [];

        compareArrayValues($array1, $array2, $diff);
        compareArrayValues($array2, $array1, $diffSecond, true);

        print_r($diff);
        print_r($diffSecond);

        print_r(array_merge($diff, $diffSecond));

Wynik:

Array
(
    [0] => DIFFERENT
    [second] => Array
        (
            [a] => Array
                (
                    [test] => DIFFERENT
                    [z] => MISSING IN FIRST
                )

        )

    [b] => MISSING IN SECOND
    [1] => DIFFERENT
    [2] => MISSING IN FIRST
)
Marko Šutija
źródło
1

Użyj funkcji php array_diff (array1, array2);

Zwróci różnicę między tablicami. Jeśli jest pusty, to są równi.

przykład:

$array1 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value3'
 );

$array2 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value4'
 );

$diff = array_diff(array1, array2);

var_dump($diff); 

//it will print array = (0 => ['c'] => 'value4' ) 

Przykład 2:

$array1 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value3',
 );

$array2 = array(
    'a' => 'value1',

    'b' => 'value2',

    'c' => 'value3',
 );

$diff = array_diff(array1, array2);

var_dump($diff); 

//it will print empty; 
Wolfgang Leon
źródło
1
Technicznie nie zwraca różnicy między tablicami. Dokumentacja stwierdza: „Porównuje tablicę 1 z co najmniej jedną inną tablicą i zwraca wartości z tablicy 1, które nie są obecne w żadnej z innych tablic.”. Tak więc, jeśli wszystkie wartości z tablicy1 są obecne w tablicy2, nawet jeśli tablica2 ma więcej wartości, array_diff zwróci pustą tablicę
2pha
Nie „wypisuje zero”, drukuje pustą tablicę (po naprawieniu kilkunastu błędów składniowych). Może możesz użyć (count(array_diff($a1, $a2)) + count(array_diff($a2, $a1))) === 0do przetestowania, czy tablice są „równe”
użytkownik9645
Naprawiłem składnię (nie null jest puste i mieszałem przecinki -.-). To, co proponujecie, myślę, że to za dużo. Sprawdzanie, czy pusta tablica powinna wystarczyć.
Wolfgang Leon
1

Jeśli chcesz sprawdzić tablice niepowiązane, oto rozwiązanie:

$a = ['blog', 'company'];
$b = ['company', 'blog'];

(count(array_unique(array_merge($a, $b))) === count($a)) ? 'Equals' : 'Not Equals';
// Equals
Santo Boldižar
źródło