¿Cómo puedo usar array_unique en una matriz de matrices?
-
23-09-2019 - |
Pregunta
Tengo una matriz
Array(
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[1] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[2] => Array
(
[0] => 33
[user_id] => 33
[1] => 8
[frame_id] => 8
)
[3] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
[4] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Como se puede ver la clave de 0 es igual a 1, 3 y 4.Y la clave 2 es diferente de todos ellos.
Cuando se ejecuta el array_unique función de ellos, lo único que nos queda es
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
Alguna idea de por qué array_unique no funciona como se espera?
Solución
Es porque array_unique
compara elementos mediante una comparación de cadenas. Desde el docs :
Nota: Se consideran dos elementos iguales si y sólo si (string) $ elem1 === (string) $ elem2. En otras palabras: cuando la representación de cadena es el mismo. Se utilizará el primer elemento.
La representación de cadena de una matriz es simplemente la palabra Array
, no importa lo que sus contenidos son.
Se puede hacer lo que quiere hacer utilizando la siguiente:
$arr = array(
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 3),
array('user_id' => 33, 'frame_id' => 8)
);
$arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'user' => int 3
2 =>
array
'user_id' => int 33
'user' => int 8
Así es como funciona:
-
Cada elemento de la matriz se serializa. Esta será único basado en la década de matriz contenido.
-
Los resultados de este se ejecutan a través
array_unique
, por lo que sólo matrices con un único firmas se dejan. -
array_intersect_key
tomará las llaves de los artículos únicos de la función de mapa / única (ya que las claves de la matriz fuente se conservan) y el tirón fuera de su fuente original array.
Otros consejos
array_unique()
sólo es compatible con matrices multidimensionales en PHP 5.2.9 y superior.
En su lugar, puede crear un hash de la matriz y compruebe que no única-dad.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
Esta es una versión mejorada del @ ryeguy de respuesta :
<?php
$arr = array(
array('user_id' => 33, 'tmp_id' => 3),
array('user_id' => 33, 'tmp_id' => 4),
array('user_id' => 33, 'tmp_id' => 5)
);
# $arr = array_intersect_key($arr, array_unique(array_map('serialize', $arr)));
$arr = array_intersect_key($arr, array_unique(array_map(function ($el) {
return $el['user_id'];
}, $arr)));
//result:
array
0 =>
array
'user_id' => int 33
'tmp_id' => int 3
En primer lugar, no hace innecesaria la serialización. En segundo lugar, a veces los atributos pueden ser diferentes, aun así la identificación es la misma.
Me he encontrado con Google Places API . Estaba combinar los resultados de varias solicitudes con diferentes tipos de objetos (piensa etiquetas). Pero tengo duplicados, ya que un objeto puede ser puesto en varias categorías (tipos). Y el método con serialize
no funcionó, ya que los attrs eran diferentes, a saber, photo_reference
y reference
. Probablemente estos son como las identificaciones temporales.
array_unique recursiva trabajo deosn't, por lo que sólo piensa "Estos son todos Array
s, vamos a matar a todos menos uno ... aquí vamos!"
Respuesta rápida (TL;DR)
- Valores distintos que puede ser extraído de la Matriz de PHP de AssociativeArrays usando foreach
- Este es un enfoque simplista
Respuesta Detallada
Contexto
- PHP 5.3
- Array de PHP de AssociativeArrays (tabluar de datos compuesto variable)
- Nombre alternativo para este compuesto variable es ArrayOfDictionary (AOD)
Problema
- Escenario: DeveloperMarsher tiene un PHP tabular compuesto variable
- DeveloperMarsher deseos para extraer valores distintos en un determinado par nombre-valor
- En el ejemplo de abajo, DeveloperMarsher desea obtener filas para cada uno de los distintos
fname
par nombre-valor
Solución
example01 ;;DeveloperMarsher comienza con un tabluar variable de datos que se parece a esto
$aodtable = json_decode('[ { "fname": "homer" ,"lname": "simpson" }, { "fname": "homer" ,"lname": "jackson" }, { "fname": "homer" ,"lname": "johnson" }, { "fname": "bart" ,"lname": "johnson" }, { "fname": "bart" ,"lname": "jackson" }, { "fname": "bart" ,"lname": "simpson" }, { "fname": "fred" ,"lname": "flintstone" } ]',true);
example01 ;;DeveloperMarsher puede extraer valores distintos con un bucle foreach que las pistas visto valores
$sgfield = 'fname'; $bgnocase = true; // $targfield = $sgfield; $ddseen = Array(); $vout = Array(); foreach ($aodtable as $datarow) { if( (boolean) $bgnocase == true ){ @$datarow[$targfield] = @strtolower($datarow[$targfield]); } if( (string) @$ddseen[ $datarow[$targfield] ] == '' ){ $rowout = array_intersect_key($datarow, array_flip(array_keys($datarow))); $ddseen[ $datarow[$targfield] ] = $datarow[$targfield]; $vout[] = Array( $rowout ); } } //;; print var_export( $vout, true );
Resultado de salida
array ( 0 => array ( 0 => array ( 'fname' => 'homer', 'lname' => 'simpson', ), ), 1 => array ( 0 => array ( 'fname' => 'bart', 'lname' => 'johnson', ), ), 2 => array ( 0 => array ( 'fname' => 'fred', 'lname' => 'flintstone', ), ), )
Trampas
- Esta solución no agregado en campos que no son parte de las DISTINTAS operación
- Arbitraria pares de nombre-valor devuelto desde elegido de forma arbitraria filas distintas
- Arbitraria orden de salida
- Arbitrario manejo de carta-caso (es capital de Una distinta de la de menor caso ?)
Ver también
- php array_intersect_key
- php array_flip
function array_unique_recursive($array)
{
$array = array_unique($array, SORT_REGULAR);
foreach ($array as $key => $elem) {
if (is_array($elem)) {
$array[$key] = array_unique_recursive($elem);
}
}
return $array;
}
No que hacer el truco?