it-swarm.com.de

PHP in_array Objektvergleich?

Kann die Funktion in_array Objekte vergleichen?

Ich habe zum Beispiel ein Array von Objekten und möchte sie eindeutig einem anderen Array hinzufügen. Ist es möglich zu überprüfen, ob ein Objekt bereits so hinzugefügt wurde:

in_array($distinct, $object);

oder gibt es einen anderen weg?

13
gorgi93

Die Funktionin_arraykann keine Objekte vergleichen.

Sie sollten eindeutige Schlüsselwertpaare aus Ihren Objekten erstellen und müssen nur diese Schlüssel vergleichen, wenn Sie ein neues Objekt in Ihr endgültiges Array einfügen.

Angenommen, dass jedes Objekt eine eindeutige id -Eigenschaft hat, wäre eine mögliche Lösung: 

$unique_objects = array();

// $data represents your object collection
foreach ($data as $item) {
    if (!array_key_exists($item->id, $unique_objects)) {
        $unique_objects[$item->id] = $obj;
    }
}
12
ukliviu

Sie können einen strengen Vergleich verwenden:

in_array($object, $array, TRUE);

Anwendungsbeispiel:

$a = new stdClass();
$a->x = 42;

$b = new stdClass();
$b->y = 42;

$c = new stdClass();
$c->x = 42;

$array = array($a,$b);

echo in_array($a, $array, true); // 1
echo in_array($b, $array, true); // 1
echo in_array($c, $array, true); //
20
Alain Tiemblo

Siehe http://php.net/manual/de/function.spl-object-hash.php

if ( ! array_key_exists( spl_object_hash( $obj ), $objects ) ) {
    $objects[ spl_object_hash( $obj ) ] = $obj;
}

Prost

2
smassey

Es gibt zahlreiche Möglichkeiten, dies zu tun, wie Sie sehen können. Ich dachte nur, ich würde noch einen hinzufügen. Ich weiß nicht warum, aber wenn ich mit Objekt-Arrays arbeite, benutze ich gerne die Array-Funktionen, die Callbacks verwenden. 

Wenn Ihre Objekte über einen Bezeichner verfügen, den sie verwenden sollten, wenn Sie sie auf Duplizierung testen möchten, funktioniert Folgendes: 

$found = array_filter($uniqueObjects, function($uniqueObject) use ($object) {
    return $uniqueObject->id == $object->id
});

if (!$found) {
    $uniqueObjects[] = $object;
}

$object ist das Objekt, nach dem Sie suchen, und $uniqueObjects ist das Array von Objekten, nach denen Sie suchen, um festzustellen, ob es vorhanden ist. Passen Sie einfach uniqueObject und object an eine identifizierende Eigenschaft an, wie z. B. eine id.

2
Kristofer Doman

Ich weiß nicht, ob es sich um eine neuere Version von PHP handelt, aber in meinem Projekt mit PHP 5.3.16 auf Ubuntu 12.04 hat es funktioniert. Es hat das Nadelobjekt in meiner Objektreihe gefunden. Ich habe auch noch einmal geprüft, indem ich ein anderes Objekt derselben Klasse lade und es mit dem Array-Inhalt teste, der dieses Objekt nicht enthielt, und es hat tatsächlich false zurückgegeben.

Ja, in_array kann Objekte vergleichen.

1
Wouter Thielen

Ich habe mir eine etwas andere, meiner Meinung nach robustere Option ausgedacht.

function array_add_unique(&$array, $new, $test, $cb) {
  if(is_array($array) && count($array)>0) {
    for($i = 0; $i < count($array); $i++) {
      if( $array[$i][$test] == $new[$test] ) {
        $do = $cb($array[$i], $new);
        if(is_bool($do) && $do) { $array[$i] = $new; }
        else if(!is_bool($do)) { $array[$i] = $do; }
        return;
      }
    }
  }
  array_Push($array, $new);
}

Der Vorteil dieser Lösung besteht darin, dass sie einen vom Benutzer definierbaren Rückruf zur Behandlung von Kollisionen enthält. Wenn Sie einzigartige Objekte hinzufügen, möchten Sie möglicherweise die Eigenschaften des alten und des neuen Objekts beibehalten.

Der Rückruf, der eine anonyme Funktion sein kann, empfängt sowohl das neue Objekt als auch das vorhandene Objekt, sodass der Benutzer eine benutzerdefinierte Berechnung durchführen kann. Rückgabe true , um das vorhandene Objekt einfach zu ersetzen oder ein neues Objekt (kein Bool) zurückzugeben, um es zu ersetzen.

Ich weiß jedoch nicht, welche Leistung dies für große Datensätze hat.

0
Kremnari

Wenn "STRICT" "FALSE" ist, erfolgt der Vergleich durch Konvertieren der Elemente in einer Zeichenfolge. Wenn Sie also die magische Funktion __toString überschreiben, sollten Sie zum Vergleichen der Objektelemente zur Verfügung stehen.

0
Justo

Ich habe einige Tests mit dem Vergleichen von Objekten mit dem in_array Funktion. Das ist meine Schlussfolgerung:

Wenn Sie versuchen, die gleiche Instanz eines Objekts in einem Array (wie OP) zu finden, dann in_array könnte mit der strengen Vergleichs-Booleschen Menge arbeiten.

Wenn Sie versuchen, ein Objekt derselben Klasse zu finden , jedoch mit einer anderen Instanz , in_array zeigt kontraintuitives Verhalten.

Es gibt ein toller Benutzerkommentar auf PHP.net über die kontraintuitiven Edge-Fälle.

// Example array

$array = array(
    'Egg' => true,
    'cheese' => false,
    'hair' => 765,
    'goblins' => null,
    'ogres' => 'no ogres allowed in this array'
);

// Loose checking -- return values are in comments

// First three make sense, last four do not

in_array(null, $array); // true
in_array(false, $array); // true
in_array(765, $array); // true
in_array(763, $array); // true
in_array('Egg', $array); // true
in_array('hhh', $array); // true
in_array(array(), $array); // true

// Strict checking

in_array(null, $array, true); // true
in_array(false, $array, true); // true
in_array(765, $array, true); // true
in_array(763, $array, true); // false
in_array('Egg', $array, true); // false
in_array('hhh', $array, true); // false
in_array(array(), $array, true); // false

Wie Sie sehen können, ohne das in_array Tests 4 - 7 ergeben keinen Sinn.

Wir wissen von PHP.net dass zwei Objekte nur im strengen Vergleich gleich sind (===), wenn sie aus derselben Klasse + Instanz stammen. Zwei Objekte sind schon im losen Vergleich gleich (==) wenn sie derselben Klasse angehören.

Ich habe einige Tests mit Objekten geschrieben, um zu sehen, was passiert.

$a = new stdClass();                              
$a->Egg = true;                                   

$b = new stdClass();                              
$b->cheese = false;                               

$c = new stdClass();                              
$c->hair = 765;                                   

$d = new stdClass();                              
$d->goblins = null;                               

$e = new stdClass();                              
$e->ogres = 'no ogres allowed in this array';     

$array2 = array($a, $b, $c,  $d, $e);         

$e = new stdClass();                                            
$e->Egg = null;                                                 

$f = new stdClass();                                            
$f->Egg = false;                                                

$g = new stdClass();                                            
$g->Egg = 765;                                                  

$h = new stdClass();                                            
$h->Egg = 763;                                                  

$i = new stdClass();                                            
$i->Egg = 'Egg';                                                

$j = new stdClass();                                            
$j->Egg = 'hhh';                                                

$k = new stdClass();                                            
$k->Egg = array();                                              

in_array($e, $array2, false); // false                
in_array($f, $array2, false); // false                
in_array($g, $array2, false); // true                 
in_array($h, $array2, false); // true                 
in_array($i, $array2, false); // true                 
in_array($j, $array2, false); // true                 
in_array($k, $array2, false); // false                

in_array($e, $array2, true); // false                 
in_array($f, $array2, true); // false                 
in_array($g, $array2, true); // false                 
in_array($h, $array2, true); // false                 
in_array($i, $array2, true); // false                 
in_array($j, $array2, true); // false                 
in_array($k, $array2, true); // false 

In den letzten Prüfungen in_array Checks 3 - 6 liefern kontraintuitive Ergebnisse.

Der Grund ist folgender. Wenn Sie versuchen, ein Objekt mit einem bestimmten Wert zu finden, müssen Sie einen losen Vergleich durchführen (da ein strenger Vergleich immer fehlschlägt, wenn die Klasse nicht dieselbe ist). Aufgrund von PHPs Variablentypen werden diese Prüfungen in den letzten Tests als wahr angesehen, da der Wert als wahr angesehen wird. Beachten Sie auch, dass der Schlüssel auf dem Objekt im losen Vergleich ignoriert wird.

0
Daan