extraño comportamiento de php array_unique
Pregunta
Estoy usando la siguiente clave de código para generar una matriz:
echo "======output without array_unique=====";
var_dump($selected);
echo "=====output with array_unique=====";
var_dump(array_unique($selected));die;
Y la salida es:
======output without array_unique=====
array
0 =>
array
'uri' => string 'http://localhost/conferences/tags/0caf4c990e0a385156b33fee58e7e3fb' (length=63)
'tag' => string '1' (length=1)
'weight' => float 4
'selected' => string 'select' (length=6)
1 =>
array
'uri' => string 'http://localhost/conferences/tags/0caf4c990e0a385156b33fee58e7e3fb' (length=63)
'tag' => string '1' (length=1)
'weight' => float 4
'selected' => string 'select' (length=6)
2 =>
array
'uri' => string 'http://localhost/conferences/tags/ffc709d5131f752df8aae22d7da4240f' (length=63)
'tag' => string '2' (length=1)
'weight' => float 4
'selected' => string '' (length=0)
3 =>
array
'uri' => string 'http://localhost/conferences/tags/035c60c7f090412cc905cee008fbeba8' (length=63)
'tag' => string '3' (length=1)
'weight' => float 0
'selected' => string '' (length=0)
4 =>
array
'uri' => string 'http://localhost/conferences/tags/4137dbc16ef1a2079eb6cacb62dd8521' (length=63)
'tag' => string '4' (length=1)
'weight' => float 0
'selected' => string '' (length=0)
=====output with array_unique=====
array
0 =>
array
'uri' => string 'http://localhost/conferences/tags/0caf4c990e0a385156b33fee58e7e3fb' (length=63)
'tag' => string '1' (length=1)
'weight' => float 4
'selected' => string 'select' (length=6)
¿Puede alguien explicarme, por qué obtengo una matriz con solo un elemento de array_unique?
Solución
Los elementos de la matriz se convierten en cadenas para su comparación: aquí está el fragmento relevante de la página de manual de para array_unique
Nota: se consideran dos elementos igual si y solo si (cadena) $ elem1 === (string) $ elem2. En palabras: cuando la representación de cadena es la misma. Se utilizará el primer elemento.
Una vez que los elementos de su matriz se convierten en cadenas, simplemente tienen el valor " Array " ;, que por supuesto hace que todos los elementos se vean iguales, y usted termina con el primer elemento.
Esta es una forma en que podría eliminar duplicados de una matriz como la suya
$seen=array();
foreach ($myarray as $key=>$val) {
if (isset($seen[$val['uri']])) {
unset($myarray[$key]); // remove duplicate
} else {
$seen[$val['uri']]=$key; // remember this
}
}
unset($seen); // don't need this any more
Otros consejos
Me imagino que dado que $ seleccionado es una matriz multidimensional, $ seleccionado [0] es lo mismo que $ seleccionado [1], una matriz.
Por lo que sé, array_unique prueba (string) $ value1 === (string) $ value2, por lo que obtienes 'Array' == 'Array'.
¿Realmente no ha explicado qué hace que un elemento sea 'único' (el URI?). Para comparar estructuras completas, es posible que desee probar en bucle a través de $ seleccionado, serializar los valores (usando serialize ()) y luego llamar a array_unique en esos valores. Luego, llame a unserialize para que la matriz vuelva a la normalidad.
<?php
function multi_array_unique($arr) {
foreach ($arr as &$elm) {
$elm = serialize($elm);
}
$arr = array_unique($arr);
foreach ($arr as &$elm) {
$elm = unserialize($elm);
}
return $arr;
}
?>
No es la solución más eficiente, pero antes de eso me preocuparía.
Consulte: http://codepad.org/6cs5b0sm
array_unique elimina duplicados al comparar el valor de cadena de los elementos. El valor de cadena de una matriz siempre es " Array " ;, independientemente del contenido de la matriz.
Esto significa que todos los elementos de su matriz tienen el valor de cadena " Array " ;, y, por lo tanto, se consideran duplicados y se eliminan, excepto la primera.
Debes escribir tu propia función array_unique que funcione comparando el 'uri' de los elementos.
Si los elementos de la matriz ya están ordenados, puede encontrar los valores únicos con esto:
$unique = array();
$n = count($array);
if ($n < 2) {
$unique = $array;
} else {
for ($i=0; $i<$n-1; ++$i) {
$unique[] = $array[$i];
if ($array[$i] === $array[$i+1]) {
++$i;
}
}
if ($i < $n && $array[$n-2] !== $array[$n-1]) {
$unique[] = $array[$n-1];
}
}