php - repeated - array_unique para objetos?
quitar duplicados php array (10)
Aquí hay una manera de eliminar objetos duplicados en una matriz:
<?php
// Here is the array that you want to clean of duplicate elements.
$array = getLotsOfObjects();
// Create a temporary array that will not contain any duplicate elements
$new = array();
// Loop through all elements. serialize() is a string that will contain all properties
// of the object and thus two objects with the same contents will have the same
// serialized string. When a new element is added to the $new array that has the same
// serialized value as the current one, then the old value will be overridden.
foreach($array as $value) {
$new[serialize($value)] = $value;
}
// Now $array contains all objects just once with their serialized version as string.
// We don''t care about the serialized version and just extract the values.
$array = array_values($new);
¿Hay algún método como array_unique para objetos? Tengo un montón de matrices con objetos ''Role'' que fusiono, y luego quiero sacar los duplicados :)
Desde aquí: http://php.net/manual/en/function.array-unique.php#75307
Este también trabajaría con objetos y matrices.
<?php
function my_array_unique($array, $keep_key_assoc = false)
{
$duplicate_keys = array();
$tmp = array();
foreach ($array as $key=>$val)
{
// convert objects to arrays, in_array() does not support objects
if (is_object($val))
$val = (array)$val;
if (!in_array($val, $tmp))
$tmp[] = $val;
else
$duplicate_keys[] = $key;
}
foreach ($duplicate_keys as $key)
unset($array[$key]);
return $keep_key_assoc ? $array : array_values($array);
}
?>
Esta es mi forma de comparar objetos con propiedades simples, y al mismo tiempo recibir una colección única:
class Role {
private $name;
public function __construct($name) {
$this->name = $name;
}
public function getName() {
return $this->name;
}
}
$roles = [
new Role(''foo''),
new Role(''bar''),
new Role(''foo''),
new Role(''bar''),
new Role(''foo''),
new Role(''bar''),
];
$roles = array_map(function (Role $role) {
return [''key'' => $role->getName(), ''val'' => $role];
}, $roles);
$roles = array_column($roles, ''val'', ''key'');
var_dump($roles);
Se producirá:
array (size=2)
''foo'' =>
object(Role)[1165]
private ''name'' => string ''foo'' (length=3)
''bar'' =>
object(Role)[1166]
private ''name'' => string ''bar'' (length=3)
Sé que ya hay una respuesta aceptada, pero aquí hay una alternativa.
Al contrario de la respuesta anterior, usa in_array()
ya que la naturaleza de comparar objetos en PHP 5 nos permite hacerlo. Hacer uso de este comportamiento de comparación de objetos requiere que la matriz solo contenga objetos, pero ese parece ser el caso aquí.
$merged = array_merge($arr, $arr2);
$final = array();
foreach ($merged as $current) {
if ( ! in_array($current, $final)) {
$final[] = $current;
}
}
var_dump($final);
También puede usar la función array_filter, si desea filtrar objetos en función de un atributo específico:
//filter duplicate objects
$collection = array_filter($collection, function($obj)
{
static $idList = array();
if(in_array($obj->getId(),$idList)) {
return false;
}
$idList []= $obj->getId();
return true;
});
También puedes serializar primero:
$unique = array_map( ''unserialize'', array_unique( array_map( ''serialize'', $array ) ) );
A partir de PHP 5.2.9, puede usar opcional sort_flag SORT_REGULAR
:
$unique = array_unique( $array, SORT_REGULAR );
array_unique funciona fundiendo los elementos en una cadena y haciendo una comparación. A menos que tus objetos se unan exclusivamente a cadenas, no funcionarán con array_unique.
En su lugar, implemente una función de comparación con estado para sus objetos y use array_filter para descartar cosas que la función ya ha visto.
de una manera sana y rápida si necesita filtrar instancias duplicadas (es decir, "===" comparación) fuera de la matriz y:
- estás seguro de qué matriz contiene solo objetos
- no necesitas llaves preservadas
es:
//sample data
$o1 = new stdClass;
$o2 = new stdClass;
$arr = [$o1,$o1,$o2];
//algorithm
$unique = [];
foreach($arr as $o){
$unique[spl_object_hash($o)]=$o;
}
$unique = array_values($unique);//optional - use if you want integer keys on output
array_unique() funciona con una matriz de objetos usando SORT_REGULAR
:
class MyClass {
public $prop;
}
$foo = new MyClass();
$foo->prop = ''test1'';
$bar = $foo;
$bam = new MyClass();
$bam->prop = ''test2'';
$test = array($foo, $bar, $bam);
print_r(array_unique($test, SORT_REGULAR));
Se imprimirá:
Array (
[0] => MyClass Object
(
[prop] => test1
)
[2] => MyClass Object
(
[prop] => test2
)
)
Véalo en acción aquí: http://3v4l.org/VvonH#v529
Advertencia : usará la comparación "==", no la comparación estricta ("===").
Por lo tanto, si desea eliminar duplicados dentro de una matriz de objetos, tenga en cuenta que comparará las propiedades de cada objeto, no comparará la identidad del objeto (instancia).
Bueno, array_unique()
compara el valor de cadena de los elementos:
Nota : Dos elementos se consideran iguales si y solo si
(string) $elem1 === (string) $elem2
es decir, cuando la representación de cadena es la misma, se usará el primer elemento.
Por lo tanto, asegúrese de implementar el método __toString()
en su clase y que __toString()
el mismo valor para roles iguales, por ejemplo
class Role {
private $name;
//.....
public function __toString() {
return $this->name;
}
}
Esto consideraría dos roles como iguales si tienen el mismo nombre.