array_diff() с многомерными массивами
С помощью array_diff()
Я могу сравнивать и удалять похожие элементы, но что если у меня есть следующие массивы?
Array1
Array
(
[0] => Array
(
[ITEM] => 1
)
[1] => Array
(
[ITEM] => 2
)
[2] => Array
(
[ITEM] => 3
)
)
array2
Array
(
[0] => Array
(
[ITEM] => 2
)
[1] => Array
(
[ITEM] => 3
)
[2] => Array
(
[ITEM] => 1
)
[3] => Array
(
[ITEM] => 4
)
)
Я хочу отфильтровать подобные предметы; результат должен вернуть 4. Как я могу изменить свой массив, чтобы я мог использовать array_diff()
?
9 ответов
Я, вероятно, перебрал бы исходные массивы и сделал бы их одномерными... что-то вроде
foreach($array1 as $aV){
$aTmp1[] = $aV['ITEM'];
}
foreach($array2 as $aV){
$aTmp2[] = $aV['ITEM'];
}
$new_array = array_diff($aTmp1,$aTmp2);
Вы можете определить пользовательскую функцию сравнения, используя array_udiff()
,
function udiffCompare($a, $b)
{
return $a['ITEM'] - $b['ITEM'];
}
$arrdiff = array_udiff($arr2, $arr1, 'udiffCompare');
print_r($arrdiff);
Выход:
Array
(
[3] => Array
(
[ITEM] => 4
)
)
Это использует и сохраняет существующую структуру массивов, которую, я полагаю, вы хотите.
Еще один забавный подход с json_encode
хитрость (может быть полезна, если вам нужно "сырое" сравнение некоторых сложных значений в массиве первого уровня):
// Compare all values by a json_encode
$diff = array_diff(array_map('json_encode', $array1), array_map('json_encode', $array2));
// Json decode the result
$diff = array_map('json_decode', $diff);
Пара решений с использованием array_filter
которые менее производительны, чем array_udiff
решение для больших массивов, но которые более просты и гибки:
$array1 = [
['ITEM' => 1],
['ITEM' => 2],
['ITEM' => 3],
];
$array2 = [
['ITEM' => 2],
['ITEM' => 3],
['ITEM' => 1],
['ITEM' => 4],
];
$arrayDiff = array_filter($array2, function ($element) use ($array1) {
return !in_array($element, $array1);
});
// OR
$arrayDiff = array_filter($array2, function ($array2Element) use ($array1) {
foreach ($array1 as $array1Element) {
if ($array1Element['ITEM'] == $array2Element['ITEM']) {
return false;
}
}
return true;
});
Как всегда с array_filter
, Обратите внимание, что array_filter
сохраняет ключи исходного массива, так что если вы хотите $arrayDiff
чтобы быть нулевым, сделать $arrayDiff = array_values($arrayDiff);
после array_filter
вызов.
Вы можете использовать приведенный ниже код, чтобы получить разницу
$a1 = Array(
[0] => Array(
[ITEM] => 1
)
[1] => Array(
[ITEM] => 2
)
[2] => Array(
[ITEM] => 3
)
);
$a2 = Array(
[0] => Array(
[ITEM] => 2
)
[1] => Array(
[ITEM] => 3
)
[2] => Array(
[ITEM] => 1
)
[3] => Array(
[ITEM] => 4
));
array_diff(array_column($a1, 'ITEM'), array_column($a2, 'ITEM'));
Возникла та же проблема, но мой многомерный массив имеет различные ключи в отличие от вашего "ПУНКТА" последовательно в каждом массиве.
Решил это с помощью: $result = array_diff_assoc($array2, $array1);
Ссылка: PHP: array_diff_assoc
Доверяйте тому, что разработчики PHP оптимизировали array_udiff()
превзойти все другие методы, которые могли бы сделать то же самое.
Что касается вашего сценария, вы ищете фильтрацию, которая оценивает данные в пределах «значения» первого уровня (строки данных). В пользовательской функции конкретный столбец должен быть изолирован для сравнения. Список всех вариантов собственных функций см . в этом ответе .
Чтобы использовать первый массив для фильтрации второго массива (и вывода сохраненных данных из второго массива), вы должны написать
$array2
в качестве первого параметра и
$array1
как второй параметр.
array_diff()
а также
array_intersect()
функции, которые используют (содержат
u
в имени своей функции) ожидают целое число в качестве возвращаемого значения. Это значение используется для предварительной сортировки данных перед фактическим выполнением оценок — это оптимизация производительности. Могут быть сценарии, когда, если вы только вернетесь
0
или же
1
(не трехстороннее сравнение), то результаты могут быть неожиданными. Чтобы гарантировать стабильный результат, всегда предоставляйте функцию сравнения, которая может возвращать отрицательное, положительное и нулевое целое число.
При сравнении целочисленных значений вычитание (
$a - $b
) даст надежные возвращаемые значения. Для большей полезности при сравнении значений с плавающей запятой или нечисловых данных вы можете использовать оператор космического корабля, когда ваша версия PHP делает его доступным.
Коды: ( Демо)
PHP7.4+ (стрелочные функции)
var_export( array_udiff($array2, $array1, fn($a, $b) => $a['ITEM'] <=> $b['ITEM']) );
PHP7+ (оператор космического корабля)
var_export( array_udiff( $array2, $array1, function($a, $b) { return $a['ITEM'] <=> $b['ITEM']; } ) );
PHP5.3+ (анонимные функции)
var_export( array_udiff( $array2, $array1, function($a, $b) { return $a['ITEM'] === $b['ITEM'] ? 0 : ($a['ITEM'] > $b['ITEM'] ? 1 : -1); } ) );
Вывод для всех версий выше:
array (
3 =>
array (
'ITEM' => 4,
),
)
При работе с массивами объектов используется тот же метод; только синтаксис для доступа к свойству отличается от доступа к элементу массива (
$a['ITEM']
было бы
$a->ITEM
).
Для сценариев, когда элемент, изолированный от одного массива, не существует в другом массиве, вам нужно будет объединить оба
$a
а также
$b
data в противоположный резервный столбец, поскольку данные из первого и второго массивов будут представлены в обоих аргументах обратного вызова.
Код: ( Демо)
$array1 = array(
array('ITEM' => 1),
array('ITEM' => 2),
array('ITEM' => 3),
);
$array2 = array(
array('ITEMID' => 2),
array('ITEMID' => 3),
array('ITEMID' => 1),
array('ITEMID' => 4),
);
// PHP7.4+ (arrow functions)
var_export(
array_udiff(
$array2,
$array1,
fn($a, $b) => ($a['ITEM'] ?? $a['ITEMID']) <=> ($b['ITEM'] ?? $b['ITEMID'])
)
);
Другое решение, если (json_encode($array1) == json_encode($array2)) {...}
Сравнивает массив1 с одним или несколькими другими массивами и возвращает значения в массиве1, которых нет ни в одном из других массивов.
//Enter your code here, enjoy!
$array1 = array("a" => "green", "red", "blue");
$array2 = array("b" => "green", "yellow", "red");
$result = array_diff($array1, $array2);
print_r($result);