PHP - Eintrag nach Objekteigenschaft aus einem Array von Objekten suchen


174

Das Array sieht folgendermaßen aus:

[0] => stdClass Object
        (
            [ID] => 420
            [name] => Mary
         )

[1] => stdClass Object
        (
            [ID] => 10957
            [name] => Blah
         )
...

Und ich habe eine ganzzahlige Variable namens $v.

Wie kann ich einen Array-Eintrag auswählen, der ein Objekt enthält, für das die IDEigenschaft den $vWert hat?

Antworten:


189

Sie iterieren entweder das Array, suchen nach dem bestimmten Datensatz (in einer einmaligen Suche in Ordnung) oder erstellen eine Hashmap mit einem anderen assoziativen Array.

Für die ersteren so etwas

$item = null;
foreach($array as $struct) {
    if ($v == $struct->ID) {
        $item = $struct;
        break;
    }
}

Weitere Informationen zu letzterem finden Sie in dieser Frage und den nachfolgenden Antworten. Referenzieren Sie das PHP-Array nach mehreren Indizes


3
Das Setzen von $ item auf null ist nicht erforderlich.
dAm2K

32
Ups, da ist es :) Das ist für den Fall, dass das gesuchte Element nicht im Array ist. Alternativ könnten Sie verwenden, isset($item)aber ich bevorzuge es, Variablen richtig zu initialisieren
Phil

3
Für diejenigen von Ihnen, deren Schlüsselwerte auf Strings gesetzt sind, verwenden Sieif($v == $struct["ID"]){...
wbadart

67

YurkamTim ist richtig. Es bedarf nur einer Änderung:

Nach der Funktion ($) benötigen Sie einen Zeiger auf die externe Variable durch "use (& $ searchedValue)" und können dann auf die externe Variable zugreifen. Sie können es auch ändern.

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use (&$searchedValue) {
        return $e->id == $searchedValue;
    }
);

2
Sie haben Recht mit der Änderung und es ist eine nette Methode, aber ich habe die Geschwindigkeit im Vergleich zum Durchlaufen des Objekts getestet - Sie selbst, denn wie @phil betont hat, macht array_filter dies auch - und diese Methode dauert ungefähr fünf mal länger. Mein Testobjekt ist kein großes, daher könnte es noch schlimmer werden.
Nicolai

9
Dies &ist beim Import $searchedValuein den Schließungsbereich nicht erforderlich . Mit &wird eine Referenz erstellt, die nur benötigt wird, wenn $searchedValuesie innerhalb des Verschlusses geändert wurde.
Stefan Gehrig

Das ist cool. Ich wusste nicht, dass PHP solche Dinge tun kann. Ich dachte, globaldie einzige Möglichkeit wäre, Daten in Funktionen zu teilen! Aber es ist schade, wenn dies tatsächlich langsam ist. :(
NoOne

13
TS hat nach einem einzelnen Eintrag gefragt, dieser Code gibt ein Array zurück.
Pavel Vlasov

57
$arr = [
  [
    'ID' => 1
  ]
];

echo array_search(1, array_column($arr, 'ID')); // prints 0 (!== false)

3
Ich bin mir nicht sicher, warum dies nicht die bevorzugte Antwort ist. Liegt es daran, dass Sie zwei Funktionen aufrufen?
doz87

1
Ich glaube ich war zu spät für die Party;) Der Mangel und die Lesbarkeit ohne Schleifen und Pausen würden es vernünftig machen. Habe es aber noch nicht bewertet. Sie haben in PHP viele Optionen, um dasselbe zu erreichen.
Tim

3
Sehr elegante Lösung. Funktioniert auch mit einem Array von Objekten in PHP 7. Für PHP 5: array_search ($ object-> id, array_map (Funktion ($ object) {return $ object-> id;}, $ Objekte)); Für PHP 7: array_search ($ object-> id, array_column ($ Objekte, 'id'));
Mike

3
Dies ist nicht die bevorzugte Antwort, da op nach einem Array von Objekten fragt und diese Antwort nur reine Arrays behandelt.
Dwza

8
das ist nicht richtig Dieser Code behandelt Array von Objekten / nicht flachen Arrays
Tim

31

Ich habe hier eine elegantere Lösung gefunden . Angepasst an die Frage könnte es so aussehen:

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);

16
+1, array_filtergibt jedoch ein Array zurück und stoppt nicht beim ersten gefundenen Wert.
Carlos Campderrós

4
Es wird $searchedValueinnerhalb der Funktion nicht erkannt . Aber draußen ist es.
M. Ahmad Zafar

4
Für den Anfang funktioniert dieser Code nicht so, wie er $searchedValueaußerhalb des Schließungsbereichs liegt. Zweitens, wie funktionieren diese Array-Methoden Ihrer Meinung nach? Sie alle durchlaufen das Array intern
Phil

1
In der Zeit der Multi-Cores könnte dies - in anderen Programmierumgebungen leider - parallel verarbeitet werden, die obige Schleife nicht unbedingt
FloydThreepwood

3
Um verwenden zu $searchedValuemüssen, schreiben Siefunction ($e) use ($searchedValue) {
Vilintritenmert

20

Wenn Sie array_column zum erneuten Indizieren verwenden, sparen Sie Zeit, wenn Sie mehrmals suchen müssen:

$lookup = array_column($arr, NULL, 'id');   // re-index by 'id'

Dann können Sie einfach $lookup[$id]nach Belieben.


3
Dies war die erstaunlichste Antwort, auch wenn es nicht die intuitivste ist ...
Thiago Natanael

11
class ArrayUtils
{
    public static function objArraySearch($array, $index, $value)
    {
        foreach($array as $arrayInf) {
            if($arrayInf->{$index} == $value) {
                return $arrayInf;
            }
        }
        return null;
    }
}

Es so zu verwenden, wie Sie es wollten, wäre ungefähr so:

ArrayUtils::objArraySearch($array,'ID',$v);


7

Wenn Sie einen kleinen Fehler im @YurkaTim beheben , funktioniert Ihre Lösung für mich, aber Sie fügen hinzu use:

Zur Nutzung $searchedValueinnerhalb der Funktion kann eine Lösung sein , use ($searchedValue)nachdem Funktionsparameter function ($e) HERE.

Die array_filterFunktion kehrt nur dann zurück, $neededObjectwenn die Bedingung für die Rückgabe lautettrue

Wenn $searchedValueist eine Zeichenfolge oder eine Ganzzahl:

$searchedValue = 123456; // Value to search.
$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);
var_dump($neededObject); // To see the output

Wenn $searchedValueist Array, wo wir mit einer Liste überprüfen müssen:

$searchedValue = array( 1, 5 ); // Value to search.
$neededObject  = array_filter(
    $arrayOfObjects,
    function ( $e ) use ( $searchedValue ) {
        return in_array( $e->term_id, $searchedValue );
    }
);
var_dump($neededObject); // To see the output

1
Ich denke, die letzte Zeile sollte sein var_dump($neededObject);:)
Sliq

3

Manchmal verwende ich gerne die Funktion array_reduce () , um die Suche durchzuführen. Es ähnelt array_filter (), wirkt sich jedoch nicht auf das gesuchte Array aus, sodass Sie mehrere Suchvorgänge für dasselbe Array von Objekten durchführen können.

$haystack = array($obj1, $obj2, ...); //some array of objects
$needle = 'looking for me?'; //the value of the object's property we want to find

//carry out the search
$search_results_array = array_reduce(
  $haystack,

  function($result_array, $current_item) use ($needle){
      //Found the an object that meets criteria? Add it to the the result array 
      if ($current_item->someProperty == $needle){
          $result_array[] = $current_item;
      }
      return $result_array;
  },
  array() //initially the array is empty (i.e.: item not found)
);

//report whether objects found
if (count($search_results_array) > 0){
  echo "found object(s): ";
  print_r($search_results_array[0]); //sample object found
} else {
  echo "did not find object(s): ";
}

1
Sie haben einen Tippfehler in Ihrer Bedingung, in dem Sie dem Ergebnisfeld hinzufügen. Es sollte dies sein:if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
adrum

Angepasst. Danke @adrum!
Yuvilio

1

Ich habe das mit einer Art Java-Keymap gemacht. In diesem Fall müssen Sie Ihr Objektarray nicht jedes Mal durchlaufen.

<?php

//This is your array with objects
$object1 = (object) array('id'=>123,'name'=>'Henk','age'=>65);
$object2 = (object) array('id'=>273,'name'=>'Koos','age'=>25);
$object3 = (object) array('id'=>685,'name'=>'Bram','age'=>75);
$firstArray = Array($object1,$object2);
var_dump($firstArray);

//create a new array
$secondArray = Array();
//loop over all objects
foreach($firstArray as $value){
    //fill second        key          value
    $secondArray[$value->id] = $value->name;
}

var_dump($secondArray);

echo $secondArray['123'];

Ausgabe:

array (size=2)
  0 => 
    object(stdClass)[1]
      public 'id' => int 123
      public 'name' => string 'Henk' (length=4)
      public 'age' => int 65
  1 => 
    object(stdClass)[2]
      public 'id' => int 273
      public 'name' => string 'Koos' (length=4)
      public 'age' => int 25
array (size=2)
  123 => string 'Henk' (length=4)
  273 => string 'Koos' (length=4)
Henk

Ah, das Array nach ID neu indizieren! Ich mache das häufig und es macht die Dinge schöner.
Kzqai

1

Weg, um sofort den ersten Wert zu erhalten:

$neededObject = array_reduce(
    $arrayOfObjects,
    function ($result, $item) use ($searchedValue) {
        return $item->id == $searchedValue ? $item : $result;
    }
);

0

Ich habe hier veröffentlicht, was ich verwende, um genau dieses Problem mithilfe eines schnellen binären Suchalgorithmus effizient zu lösen: https://stackoverflow.com/a/52786742/1678210

Ich wollte nicht die gleiche Antwort kopieren. Jemand anderes hatte es etwas anders gefragt, aber die Antwort ist dieselbe.

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.