uniques - php array unique objects
¿Cómo uso array_unique en una matriz de matrices? (6)
Respuesta rápida (TL; DR)
- Se pueden extraer valores distintos de PHP Array of AssociativeArrays usando foreach
- Este es un enfoque simplista.
Respuesta detallada
Contexto
- PHP 5.3
- PHP Array of AssociativeArrays (variable de datos compuestos de tabluar)
- El nombre alternativo para esta variable compuesta es ArrayOfDictionary (AOD)
Problema
- Escenario: DeveloperMarsher tiene una variable compuesta tabular de PHP
- DeveloperMarsher desea extraer valores distintos en un par de nombre-valor específico
- En el siguiente ejemplo, DeveloperMarsher desea obtener filas para cada
fname
nombre-valorfname
distinto
Solución
example01 ;; DeveloperMarsher comienza con una variable de datos de cuadro que se ve así
$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 rastrea los valores vistos
$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'', ), ), )
Escollos
- Esta solución no se agrega a los campos que no forman parte de la operación DISTINCT
- Los pares de nombre-valor arbitrarios se devuelven desde filas distintas elegidas arbitrariamente
- Orden de salida arbitrario
- Manejo arbitrario de mayúsculas y minúsculas (¿el capital es distinto de la minúscula a?)
Ver también
- php array_intersect_key
- php array_flip
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 puede ver, la clave 0 es igual a 1,3 y 4. Y la clave 2 es diferente de todas ellas.
Cuando se ejecuta la función array_unique en ellos, lo único que queda es
Array (
[0] => Array
(
[0] => 33
[user_id] => 33
[1] => 3
[frame_id] => 3
)
)
¿Alguna idea de por qué array_unique no está funcionando como se esperaba?
Aquí hay una versión mejorada de la respuesta de @ ryeguy :
<?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
Primero, no hace una serialización innecesaria. En segundo lugar, a veces los atributos pueden ser diferentes, así que id es el mismo
Me he encontrado con la API de Google Places . Estaba combinando los resultados de varias solicitudes con diferentes tipos de objetos (etiquetas de pensar). Pero tengo duplicados, ya que un objeto puede ser colocado en varias categorías (tipos). Y el método con serialize
no funcionó, ya que los atributos eran diferentes, a saber, photo_reference
y reference
. Probablemente estos son como identificadores temporales.
Es porque array_unique
compara elementos utilizando una comparación de cadena. De los docs :
Nota: Dos elementos se consideran iguales si y solo si (cadena) $ elem1 === (cadena) $ elem2. En palabras: cuando la representación de cadena es la misma. Se utilizará el primer elemento.
La representación de cadena de una matriz es simplemente la palabra Array
, independientemente de su contenido.
Puedes hacer lo que quieras hacer usando lo 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. Esto será único basado en el contenido de la matriz.
Los resultados de esto se ejecutan a través de
array_unique
, por lo que solo quedan matrices con firmas únicas.array_intersect_key
tomará las claves de los elementos únicos del mapa / función única (ya que se conservan las claves de la matriz de origen) y las sacará de su matriz de origen original.
array_unique no funciona de forma recursiva, por lo que solo piensa "esto es todo Array
s, matemos a todos menos a uno ... ¡aquí vamos!"
array_unique()
solo admite matrices multidimensionales en PHP 5.2.9 y superior.
En su lugar, puede crear un hash de la matriz y verificar si es único.
$hashes = array();
foreach($array as $val) {
$hashes[md5(serialize($val))] = $val;
}
array_unique($hashes);
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;
}
¿Eso no hace el truco?