Reputation: 23
I'm trying to get non matching items between 2 multidimensional arrays using the 'nombre_entrada', 'precio_productor' and 'id_funcion' to compare. I tried with array_search/array_column but didn't work.
What I need is to get a new array containing the items not matching.
Array 1
Array(
[0] => Array
(
[nombre_entrada] => Entrada General
[precio_productor] => 250
[id_funcion] => 907
)
[1] => Array
(
[nombre_entrada] => Entrada General
[precio_productor] => 300
[id_funcion] => 907
)
[2] => Array
(
[nombre_entrada] => Entrada General
[precio_productor] => 350
[id_funcion] => 907
)
[3] => Array
(
[nombre_entrada] => 2 entradas x
[precio_productor] => 400
[id_funcion] => 907
)
)
Array 2
Array
(
[0] => Array
(
[nombre_entrada] => Entrada General
[precio_productor] => 350
[id_funcion] => 907
)
[1] => Array
(
[nombre_entrada] => 2 entradas x
[precio_productor] => 400
[id_funcion] => 907
)
)
In the Array 1 index 0 and 1 not exists in Array 2 so I need to create a final array including those items.
Final Array
Array(
[0] => Array
(
[nombre_entrada] => Entrada General
[precio_productor] => 250
[id_funcion] => 907
)
[1] => Array
(
[nombre_entrada] => Entrada General
[precio_productor] => 300
[id_funcion] => 907
)
)
Upvotes: 1
Views: 1446
Reputation: 18416
You can also use array_filter
with !in_array
, which accepts an array as the $needle
argument. It works similarly to array_udiff($array1, $array2, function($a, $b) { return $a <=> $b; })
, but will disregard the array keys, is compatible with PHP 5.3+ and does not need to iterate over the source array with serialize()
which would be costly with a very large array.
$array1 = array(
array
(
'nombre_entrada' => 'Entrada General',
'precio_productor' => 250,
'id_funcion' => 907,
),
array
(
'nombre_entrada' => 'Entrada General',
'precio_productor' => 300,
'id_funcion' => 907,
),
array
(
'nombre_entrada' => 'Entrada General',
'precio_productor' => 350,
'id_funcion' => 907,
),
array
(
'nombre_entrada' => '2 entradas x',
'precio_productor' => 400,
'id_funcion' => 907,
)
);
$array2 = array(
array
(
'precio_productor' => 350, //note array key was moved
'nombre_entrada' => 'Entrada General',
'id_funcion' => 907,
),
array
(
'nombre_entrada' => '2 entradas x',
'precio_productor' => 400,
'id_funcion' => 907,
),
);
$missing = array_filter($array1, function($v) use ($array2) {
return !in_array($v, $array2);
});
var_export($missing);
Result:
array (
0 =>
array (
'nombre_entrada' => 'Entrada General',
'precio_productor' => 250,
'id_funcion' => 907,
),
1 =>
array (
'nombre_entrada' => 'Entrada General',
'precio_productor' => 300,
'id_funcion' => 907,
),
)
Alternatively If you want to account for the array keys, you can pass true as the third argument to in_array($v, $array2, true)
, which will cause a strict comparison, which is equivalent to $a <=> $b
.
As a simpler solution using serialize
, instead of iterating over the array, you can compare the values directly using array_udiff
and strcmp
. Though I recommend using $a <=> $b
(spaceship operator) instead if you have PHP 7.0+
$missing = array_udiff($array1, $array2, function($a, $b) {
return strcmp(serialize($a), serialize($b));
});
Upvotes: 0
Reputation: 41810
This is generally the functionality of array_diff
.
You can't use array_diff
for it directly because it compares the string representation of the array items to find the difference, and arrays don't have a distinct string representation. (They all just convert to "Array".)
PHP can compare arrays though, and if you use array_udiff
you can just compare them directly in the comparison function without converting to string.
$result = array_udiff($array1, $array2, function($a, $b) { return $a <=> $b; });
Upvotes: 2
Reputation: 23
I was able to create the array in this way
$newArray = array();
foreach ($detectadas as $item) {
if (
array_search($item['nombre_entrada'], array_column($entradasResult2, 'nombre_entrada')) === false OR
array_search($item['precio_productor'], array_column($entradasResult2, 'precio_productor')) === false OR
array_search($item['id_funcion'], array_column($entradasResult2, 'id_funcion')) === false
) {
array_push( $newArray, $item );
}
}
Upvotes: 0
Reputation: 54831
Rather tricky solution, it works only inf you need compare all 3 keys and if order of keys in all subarray are the same:
// first rebuild second array to new array
// where key is serialized value of value:
$newArray = [];
foreach ($array2 as $item) {
$newArray[serialize($item)] = $item;
}
// next - filter your first array:
$filteredArray = array_filter(
$array1,
function($v) use ($newArray) {
// here serialize `$v` and check if key
// same as serialized `$v` exists in $newArray
return !isset($newArray[serialize($v)]);
}
);
Working fiddle https://3v4l.org/aKba9.
Upvotes: 0