values uniques unico remove objects multidimensional how from eliminar duplicate duplicados check array_unique array php arrays array-unique

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-valor fname 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:

  1. Cada elemento de la matriz se serializa. Esto será único basado en el contenido de la matriz.

  2. Los resultados de esto se ejecutan a través de array_unique , por lo que solo quedan matrices con firmas únicas.

  3. 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?