strano comportamento di php array_unique
Domanda
Sto usando il seguente codice di pace per generare un array:
echo "======output without array_unique=====";
var_dump($selected);
echo "=====output with array_unique=====";
var_dump(array_unique($selected));die;
E l'output è:
======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)
Qualcuno può spiegarmi, perché ottengo array con un solo elemento da array_unique?
Soluzione
Gli elementi dell'array vengono convertiti in stringhe per il confronto: ecco lo snippet pertinente dalla pagina del manuale per array_unique
Nota: vengono considerati due elementi uguale se e solo se (stringa) $ elem1 === (stringa) $ elem2. A parole: quando la rappresentazione della stringa è la stessa. Verrà utilizzato il primo elemento.
Una volta che gli elementi dell'array vengono convertiti in stringhe, hanno semplicemente il valore "Array", che ovviamente rende ogni elemento uguale e si finisce con il primo elemento.
Ecco un modo per rimuovere i duplicati da un array come il tuo
$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
Altri suggerimenti
Immagino che dato che $ selected è un array multidimensionale, $ selected [0] è uguale a $ selected [1], un array.
Per quanto ne so, array_unique testa (stringa) $ value1 === (stringa) $ value2, quindi ottieni 'Array' == 'Array'.
Non hai davvero spiegato cosa rende un elemento "unico" (l'URI?). Per confrontare intere strutture, potresti provare a scorrere in loop $ selezionati, serializzando i valori (usando serialize ()) e quindi chiamando array_unique su quei valori. Quindi, chiamare unserialize per riportare l'array alla normalità.
<?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;
}
?>
Non è la soluzione più efficiente, ma vorrei fare un benchmark prima, prima di preoccuparmene.
array_unique rimuove i duplicati confrontando il valore di stringa degli elementi. Il valore di stringa di un array è sempre " Array " ;, indipendente dal contenuto dell'array.
Ciò significa che tutti gli elementi dell'array hanno il valore di stringa "Array" e sono pertanto considerati duplicati e vengono rimossi tranne il primo.
Dovresti scrivere la tua funzione array_unique che funziona confrontando 'uri' degli elementi.
Se gli elementi dell'array sono già ordinati, puoi trovare i valori univoci con questo:
$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];
}
}