Esiste un metodo come array_unique per gli oggetti? Ho un sacco di array con gli oggetti 'ruolo' che unire e quindi voglio prendere i duplicati :)array_unique per gli oggetti?
risposta
bene, array_unique()
confronta il valore stringa degli elementi:
Nota : Due elementi sono considerati uguali se e solo se
(string) $elem1 === (string) $elem2
cioè quando la rappresentazione della stringa è la stessa, verrà utilizzato il primo elemento.
Assicurati quindi di implementare il metodo __toString()
nella classe e di restituire lo stesso valore per ruoli uguali, ad es.
class Role {
private $name;
//.....
public function __toString() {
return $this->name;
}
}
Questo considererebbe due ruoli uguali se hanno lo stesso nome.
grazie =) sembra funzionare bene per me;) – Johannes
@Jacob perché né 'array_unique' né' __toString() 'mettono a confronto nulla. '__toString()' definisce il comportamento di un'istanza di un oggetto quando viene utilizzato in un contesto di stringa e 'array_unique' restituisce l'array di input con i valori duplicati rimossi. Solo * usa * il confronto per questo internamente. – Gordon
@Jacob Relkin: non è un comparatore. È la rappresentazione di stringa dell'oggetto. Penso che lo usino in quanto è possibile convertire qualsiasi tipo, oggetto, ecc. In una stringa. Ma il metodo stringa stesso su un oggetto non viene utilizzato solo da questa funzione. Per esempio. 'echo $ object' usa anche il metodo' __toString'. –
Da qui: http://php.net/manual/en/function.array-unique.php#75307
Questo dovrebbe funzionare con gli oggetti e gli array anche.
<?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);
}
?>
Grazie mille. –
@Richard Knop, siete i benvenuti, buona fortuna! –
Grazie mille per il post @SilverLight ha votato per questo sforzo ancora una volta – Amjad
So che c'è già una risposta accettata, ma ecco un'alternativa.
Contrariamente alla risposta precedente, utilizza in_array()
poiché la natura di comparing objects in PHP 5 ci consente di farlo. Facendo uso di questo comportamento di confronto degli oggetti è necessario che l'array solo contenga oggetti, ma sembra che sia il caso qui.
$merged = array_merge($arr, $arr2);
$final = array();
foreach ($merged as $current) {
if (! in_array($current, $final)) {
$final[] = $current;
}
}
var_dump($final);
Funziona bene, potrebbe essere più veloce dell'altro (non lo so davvero) ma userò il tuo perché non devo prendere extra funzione per questo: D – Gigala
Quando si confrontano gli oggetti devono avere la stessa quantità di campi e devono essere identiche coppie chiave/valore da considerare uguali? quello che sto cercando è .... se ho 2 oggetti e uno di loro ha un campo in più, quegli oggetti non saranno considerati "uguali" – ChuckKelly
'in_array' dovrebbe usare il parametro' $ strict'! Altrimenti, stai confrontando gli oggetti usando "==" invece di "===". Maggiori informazioni qui: http://fr2.php.net/manual/fr/function.in-array.php –
array_unique funziona convertendo gli elementi in una stringa e facendo un confronto. A meno che i tuoi oggetti non vengano espressi in modo univoco per le stringhe, non funzioneranno con array_unique.
Invece, implementare una funzione di confronto stateful per i propri oggetti e utilizzare array_filter per eliminare elementi che la funzione ha già visto.
Ero in giro per una soluzione più elegante (una che non richiederebbe callback). Tuttavia, apprezza la tua risposta. –
'array_unique' usato con SORT_REGULAR funziona, vedere la mia risposta qui sotto. –
Ecco un modo per rimuovere gli oggetti duplicati in un array:
<?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);
La risposta qui è ottima e offre una soluzione per gli oggetti che sono istanze di classi personalizzate, ma non vedo come possa funzionare per le istanze di base di stdClass. –
@Emanuil: vero. Ho aggiunto un'altra risposta alla mia risposta. – yankee
Puoi aggiungere qualche commento su questo codice? Non penso di averlo capito. –
È inoltre possibile serializzare prima:
$unique = array_map('unserialize', array_unique(array_map('serialize', $array)));
Dal PHP 5.2.9 si può semplicemente utilizzare opzionale sort_flag SORT_REGULAR
:
$unique = array_unique($array, SORT_REGULAR);
array_unique
lavori con una serie di oggetti utilizzando 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));
stamperà:
Array (
[0] => MyClass Object
(
[prop] => test1
)
[2] => MyClass Object
(
[prop] => test2
)
)
vederlo in azione qui: http://3v4l.org/VvonH#v529
Avviso: utilizzerà il confronto "==", non il confronto stretto ("===").
Quindi, se si desidera rimuovere i duplicati all'interno di una matrice di oggetti, fare attenzione a confrontare ciascuna proprietà dell'oggetto, non confrontare l'identità dell'oggetto (istanza).
Questa risposta è molto meglio della risposta accettata. Tuttavia l'esempio non mostra la differenza tra il confronto sul valore ('==') o l'identità ('===') a causa di '$ bam-> prop = 'test2';' (dovrebbe essere ''test1'' per mostrare la differenza). Vedi http://codepad.viper-7.com/8NxWhG per un esempio. – Flip
@Flip concordato. Questa risposta è molto meglio. Upvoted. – MikeSchinkel
fantastico .... :) come studiare queste cose per array di oggetti e array normali? – Vishal
È inoltre possibile utilizzare la funzione che array_filter, se si desidera filtrare gli oggetti in base a un attributo specifico:
//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;
});
modo sano e veloce se avete bisogno di filtrare le istanze duplicate (vale a dire "===" confronto) di matrice e:
- siete sicuri di cosa array contiene solo oggetti
- non avete bisogno di chiavi conservate
è:
//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
duplicato di http://stackoverflow.com/questions/1050709/how-can-i-remove-duplicates-in-an-object-array-in-php/ –