сравнивая массивы в php, не заботясь о порядке - PullRequest
13 голосов
/ 23 декабря 2010

У меня есть два массива, $ a и $ b, и я должен проверить, содержат ли они абсолютно одинаковые элементы (независимо от порядка). Я думаю об использовании

if (sizeof($a)==sizeof($b) AND array_diff($a,$b)==array())
{

}

Но я новичок в PHP, поэтому мне интересно: есть ли лучший способ?

Поскольку мне нужно использовать их как наборы, возможно, мне не следует использовать массивы вообще, а что-то еще.

Ответы [ 5 ]

12 голосов
/ 23 декабря 2010

Ну, мы можем сделать что-то вроде этого:

if (count(array_diff(array_merge($a, $b), array_intersect($a, $b))) === 0) {
    //they are the same!
}

Причина, по которой это работает, заключается в том, что array_merge создаст большой массив, содержащий все элементы как $a и $b (все элементы, которые находятся либо в $a, $b или оба). array_intersect создаст массив, содержащий все элементы только в $a и $b. Так что, если они разные, должен быть хотя бы один элемент, который не появляется в обоих массивах ...

Также обратите внимание, что sizeof не является реальной функцией / конструкцией, это псевдоним. Я бы предложил использовать count() для ясности ...

6 голосов
/ 27 мая 2016

Принятый ответ неверен!Это не удастся: https://3v4l.org/U8U5p

$a = ['x' => 1, 'y' => 2]; $b = ['x' => 1, 'y' => 1];

Вот правильное решение:

function consistsOfTheSameValues(array $a, array $b)
{
    // check size of both arrays
    if (count($a) !== count($b)) {
        return false;
    }

    foreach ($b as $key => $bValue) {

        // check that expected value exists in the array
        if (!in_array($bValue, $a, true)) {
            return false;
        }

        // check that expected value occurs the same amount of times in both arrays
        if (count(array_keys($a, $bValue, true)) !== count(array_keys($b, $bValue, true))) {
            return false;
        }

    }

    return true;
}

Плюс довольно обширные юнит-тесты: https://3v4l.org/m6lHv

<?php

// A unit testing framework in a tweet. https://gist.github.com/mathiasverraes/9046427
function it($m,$p){echo ($p?'✔︎':'✘')." It $m\n"; if(!$p){$GLOBALS['f']=1;}}function done(){if(@$GLOBALS['f'])die(1);}

function consistsOfTheSameValues(array $a, array $b)
{
    // check size of both arrays
    if (count($a) !== count($b)) {
        return false;
    }

    foreach ($b as $key => $bValue) {

        // check that expected value exists in the array
        if (!in_array($bValue, $a, true)) {
            return false;
        }

        // check that expected value occurs the same amount of times in both arrays
        if (count(array_keys($a, $bValue, true)) !== count(array_keys($b, $bValue, true))) {
            return false;
        }

    }

    return true;
}

it('consist of the same values',
    consistsOfTheSameValues([1], [1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues([1, 1], [1, 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['1', 1], ['1', 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['1', 1], [1, '1']) === true
);

it('consist of the same values',
    consistsOfTheSameValues([1, '1'], ['1', 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues([1, '1'], [1, '1']) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['x' => 1], ['x' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['x' => 1], ['y' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['y' => 1], ['x' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['x' => 1, 'y' => 1], ['x' => 1, 'y' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['y' => 1, 'x' => 1], ['x' => 1, 'y' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['x' => 1, 'y' => 1], ['y' => 1, 'x' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['y' => 1, 'x' => 1], ['y' => 1, 'x' => 1]) === true
);

it('consist of the same values',
    consistsOfTheSameValues(['x' => 2, 'y' => 1], ['x' => 1, 'y' => 2]) === true
);

it('does not consist of the same values',
    consistsOfTheSameValues([1], [2]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['1'], [1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1], ['1']) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1], [1, 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1, 1], [1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['1', 1], [1, 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1, '1'], [1, 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1, 1], ['1', 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1, 1], [1, '1']) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['1', '1'], [1, 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['1', '1'], ['1', 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['1', '1'], [1, '1']) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1, 1], ['1', '1']) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['1', 1], ['1', '1']) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues([1, '1'], ['1', '1']) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['x' => 1], ['x' => 2]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['x' => 1, 'y' => 1], ['x' => 1, 'y' => 2]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['x' => 1, 'y' => 1], ['x' => 2, 'y' => 1]) === false
);

it('does not consist of the same values',
    consistsOfTheSameValues(['x' => 2, 'y' => 1], ['x' => 1, 'y' => 1]) === false
);

@ обновление:

Обширный модульный тест @ircmaxell ответ: https://3v4l.org/5ivgm

Обширный модульный тест @Jon anwser: https://3v4l.org/CrTgQ

4 голосов
/ 25 мая 2017

Принятый ответ не учитывает дубликаты. Вот мой дубль

public function sameElements($a, $b)
{
   sort($a);
   sort($b);
   return $a == $b;
}
2 голосов
/ 23 декабря 2010

Просто для вашего удовольствия я добавлю пример, который демонстрирует, что ваши условия не верны:

<?php
$a = array(1, 1, 2);
$b = array(1, 2, 3);

var_dump(sizeof($a)==sizeof($b) AND array_diff($a,$b)==array());
?>

Проверьте это.

Я бы предложил использоватьдругая модель.Возможно добавление элементов в качестве ключей массива, но это возможно, только если они являются целыми числами или строками.

$arr['itemA'] = true;
$arr['itemB'] = true;

Это обеспечит уникальность.С этой моделью вы можете использовать ваше состояние на array_keys($arr).

2 голосов
/ 23 декабря 2010

Если вы думаете о массивах как о наборах :

Тогда ваш подход почти правильный (вам нужно отбросить тест на равенство для количества элементов).

Если важно, чтобы массивы содержали несколько копий одного и того же элемента :

, тогда ваш подход не правильный.Вам нужно отсортировать массивы с помощью sort, а затем сравнить их с ===.Это должно быть быстрее, так как он может прервать сравнение в тот момент, когда видит одно различие, не проходя через все массивы.

Обновление:

Уточняется точно, когда приближается ОПбыло бы правильно или нет, также включены предположения, что sort будет, вероятно, лучше, чем asort здесь.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...