сравнение массивов в php, не заботясь о порядке
У меня есть два массива, $a и $b здесь, и мне нужно проверить, содержат ли они точно такие же элементы (независимо от порядка). Я подумываю об использовании
if (sizeof($a)==sizeof($b) AND array_diff($a,$b)==array())
{
}
Но я новичок в PHP, поэтому мне интересно: есть ли лучший способ?
Поскольку мне нужно использовать их как наборы, возможно, мне вообще не следует использовать массивы, а что-то другое.
5 answers
Ну, мы можем сделать что-то вроде этого:
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()
для ясности...
Принятый ответ неверен! Это приведет к сбою при: 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
Просто для вашего развлечения я добавлю пример, который демонстрирует, что ваши условия неверны:
<?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)
.
Если вы думаете о массивах как о наборах:
Тогда ваш подход почти правильный (вам нужно отказаться от теста на равенство для количества элементов).
Если имеет значение, что массивы содержат несколько копий одного и того же элемента:
Тогда ваш подход неверен . Вам нужно отсортировать массивы с помощью sort
а затем сравните их с ===
. Это должно быть быстрее, так как оно может прервать сравнение в тот момент, когда увидит его разница без просмотра всех массивов.
Обновление:
Точно разъяснил, когда подход ОП будет правильным или нет, также включил предположение, что sort
, вероятно, будет лучше, чем asort
здесь.
Принятый ответ не учитывает дубликаты. Вот мое мнение
public function sameElements($a, $b)
{
sort($a);
sort($b);
return $a == $b;
}