Quick example for using array_udiff to do a multi-dimensional diff
Returns values of $arr1 that are not in $arr2
<?php
$arr1 = array( array('Bob', 42), array('Phil', 37), array('Frank', 39) );
$arr2 = array( array('Phil', 37), array('Mark', 45) );
$arr3 = array_udiff($arr1, $arr2, create_function(
'$a,$b',
'return strcmp( implode("", $a), implode("", $b) ); ')
);
print_r($arr3);
?>
Output:
Array
(
[0] => Array
(
[0] => Bob
[1] => 42
)
[2] => Array
(
[0] => Frank
[1] => 39
)
)
1
Hope this helps someone
array_udiff
(PHP 5)
array_udiff — Computa la diferencia entre arrays, usando una llamada de retorno para la comparación de datos
Descripción
Computa la diferencia de los arrays usando una función tipo llamada de retorno para la comparación de datos. Esto difiere de array_diff(), la cual usa una función interna para la comparación de datos.
Parámetros
-
array1 -
El primer array.
-
array2 -
El segundo array
-
data_compare_func -
La función llamada de retorno para la comparación.
La función de comparación debe devolver un entero menor, igual o mayor que cero si el primer argumento se considera que sea respectivamente menor, igual o mayor que el segundo.
Valores devueltos
Devuelve un array que contiene todos los valores de array1
que no están presentes en ninguno de los otros argumentos.
Ejemplos
Ejemplo #1 Ejemplo de array_udiff()
<?php
class cr {
private $miembro_privado;
function cr($val)
{
$this->miembro_privado = $val;
}
static function func_comp_cr($a, $b)
{
if ($a->miembro_privado === $b->miembro_privado) return 0;
return ($a->miembro_privado > $b->miembro_privado)? 1:-1;
}
}
$a = array("0.1" => new cr(9), "0.5" => new cr(12), 0 => new cr(23), 1=> new cr(4), 2 => new cr(-15),);
$b = array("0.2" => new cr(9), "0.5" => new cr(22), 0 => new cr(3), 1=> new cr(4), 2 => new cr(-15),);
$resultado = array_udiff($a, $b, array("cr", "func_comp_cr"));
print_r($resultado);
?>
El resultado del ejemplo sería:
Array
(
[0.5] => cr Object
(
[miembro_privado:private] => 12
)
[0] => cr Object
(
[miembro_privado:private] => 23
)
)
Notas
Nota: Por favor note que esta función sólo analiza una dimensión de un array n-dimensional. Por supuesto, puede analizar dimensiones más profundas usando array_udiff($array1[0], $array2[0], "data_compare_func");.
Ver también
- array_diff() - Calcula la diferencia entre arrays
- array_diff_assoc() - Calcula la diferencia entre arrays con un chequeo adicional de índices
- array_diff_uassoc() - Calcula la diferencia entre arrays con un chequeo adicional de índices que se realiza por una función de devolución de llamada suministrada por el usuario
- array_udiff_assoc() - Computa la diferencia entre arrays con una comprobación de indices adicional, compara la información mediante una función de llamada de retorno
- array_udiff_uassoc() - Computa la diferencia entre arrays con una verificación de índices adicional, compara la información y los índices mediante una función de llamada de retorno
- array_intersect() - Calcula la intersección de arrays
- array_intersect_assoc() - Calcula la intersección de arrays con un chequeo adicional de índices
- array_uintersect() - Computa una intersección de arrays, compara la información mediante una función de llamada de retorno
- array_uintersect_assoc() - Computa la intersección de arrays con una comprobación de índices adicional, compara la información mediante una función de llamada de retorno
- array_uintersect_uassoc() - Computa la intersección de arrays con una comprobación de índices adicional, compara la información y los índices mediante funciones de llamada de retorno
Note that php does the string conversion *before* sending the values to the callback function.
It is not stated, by this function also diffs array1 to itself, removing any duplicate values...
Re: "convoluted"
I think the point being made is that array_udiff() can be used not only for comparisons between homogenous arrays, as in your example (and definitely the most common need), but it can be used to compare heterogeneous arrays, too.
Consider:
<?php
function compr_1($a, $b) {
$aVal = is_array($a) ? $a['last_name'] : $a;
$bVal = is_array($b) ? $b['last_name'] : $b;
return strcasecmp($aVal, $bVal);
}
$aEmployees = array(
array('last_name' => 'Smith',
'first_name' => 'Joe',
'phone' => '555-1000'),
array('last_name' => 'Doe',
'first_name' => 'John',
'phone' => '555-2000'),
array('last_name' => 'Flagg',
'first_name' => 'Randall',
'phone' => '666-1000')
);
$aNames = array('Doe', 'Smith', 'Johnson');
$result = array_udiff($aEmployees, $aNames, "compr_1");
print_r($result);
?>
Allowing me to get the "employee" that's not in the name list:
Array ( [2] => Array ( [last_name] => Flagg [first_name] => Randall [phone] => 666-1000 ) )
Something interesting to note, is that the two arguments to the compare function don't correspond to array1 and array2. That's why there has to be logic in it to handle that either of the arguments might be pointing to the more complex employee array. (Found this out the hard way.)
I think the example given here using classes is convoluting things too much to demonstrate what this function does.
array_udiff() will walk through array_values($a) and array_values($b) and compare each value by using the passed in callback function.
To put it another way, array_udiff() compares $a[0] to $b[0], $b[1], $b[2], and $b[3] using the provided callback function. If the callback returns zero for any of the comparisons then $a[0] will not be in the returned array from array_udiff(). It then compares $a[1] to $b[0], $b[1], $b[2], and $b[3]. Then, finally, $a[2] to $b[0], $b[1], $b[2], and $b[3].
For example, compare_ids($a[0], $b[0]) === -5 while compare_ids($a[1], $b[1]) === 0. Therefore, $a[1] is not returned from array_udiff() since it is present in $b.
<?
$a = array(
array(
'id' => 10,
'name' => 'John',
'color' => 'red',
),
array(
'id' => 20,
'name' => 'Elise',
'color' => 'blue',
),
array(
'id' => 30,
'name' => 'Mark',
'color' => 'red',
),
);
$b = array(
array(
'id' => 15,
'name' => 'Nancy',
'color' => 'black',
),
array(
'id' => 20,
'name' => 'Elise',
'color' => 'blue',
),
array(
'id' => 30,
'name' => 'Mark',
'color' => 'red',
),
array(
'id' => 40,
'name' => 'John',
'color' => 'orange',
),
);
function compare_ids($a, $b)
{
return ($a['id'] - $b['id']);
}
function compare_names($a, $b)
{
return strcmp($a['name'], $b['name']);
}
$ret = array_udiff($a, $b, 'compare_ids');
var_dump($ret);
$ret = array_udiff($b, $a, 'compare_ids');
var_dump($ret);
$ret = array_udiff($a, $b, 'compare_names');
var_dump($ret);
?>
Which returns the following.
In the first return we see that $b has no entry in it with an id of 10.
<?
array(1) {
[0]=>
array(3) {
["id"]=>
int(10)
["name"]=>
string(4) "John"
["color"]=>
string(3) "red"
}
}
?>
In the second return we see that $a has no entry in it with an id of 15 or 40.
<?
array(2) {
[0]=>
array(3) {
["id"]=>
int(15)
["name"]=>
string(5) "Nancy"
["color"]=>
string(5) "black"
}
[3]=>
array(3) {
["id"]=>
int(40)
["name"]=>
string(4) "John"
["color"]=>
string(6) "orange"
}
}
?>
In third return we see that all names in $a are in $b (even though the entry in $b whose name is 'John' is different, the anonymous function is only comparing names).
<?
array(0) {
}
?>
Very easy way of achieving a case-insensitive version of array_diff (or indeed array_diff_assoc, array_intersect or any of these types of functions which have a similar function that takes a callback function as one of their parameters):
array_udiff($array1, $array2, 'strcasecmp');
This works because strcasecmp() compares two strings case-insensitively, as compared to the array_diff() which compares two strings by using the == operator, which is case-sensitive.
This functionality is now implemented in the PEAR package PHP_Compat.
More information about using this function without upgrading your version of PHP can be found on the below link:
http://pear.php.net/package/PHP_Compat
