web-dev-qa-db-fra.com

PHP - rechercher une entrée par propriété d'objet dans un tableau d'objets

Le tableau ressemble à:

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

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

Et j'ai une variable entière appelée $v.

Comment puis-je sélectionner une entrée de tableau qui a un objet où la propriété 'ID' a la valeur $v?

126
Alex

Vous pouvez soit parcourir le tableau, rechercher un enregistrement particulier (ok dans une recherche unique), soit créer une table de hachage en utilisant un autre tableau associatif.

Pour les anciens, quelque chose comme ça

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

Voir cette question et les réponses ultérieures pour plus d'informations sur cette dernière - Référence PHP tableau par plusieurs index

151
Phil

YurkamTim a raison. Cela nécessite seulement une modification: (Désolé, je ne peux pas commenter maintenant).

Après la fonction ($), vous avez besoin d’un pointeur sur la variable externe avec "use (& $ searchValue)" pour pouvoir accéder à la variable externe. Aussi, vous pouvez le modifier.

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

J'ai trouvé une solution plus élégante ici . Adapté à la question, cela peut ressembler à:

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) {
        return $e->id == $searchedValue;
    }
);
21
YurkaTim
$arr = [
  [
    'ID' => 1
  ]
];

echo array_search(1, array_column($arr, 'ID')); // prints 0 (!== false)
18
Tim
class ArrayUtils
{
    public static function objArraySearch($array, $index, $value)
    {
        foreach($array as $arrayInf) {
            if($arrayInf->{$index} == $value) {
                return $arrayInf;
            }
        }
        return null;
    }
}

En utilisant ce que vous vouliez, ce serait quelque chose comme:

ArrayUtils::objArraySearch($array,'ID',$v);
8
Pablo S G Pacheco

Utiliser array_column pour réindexer vous fera gagner du temps si vous devez rechercher plusieurs fois:

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

Ensuite, vous pouvez simplement $lookup[$id] à volonté.

6
Museful

Corriger une petite erreur de @YurkaTim , votre solution marche pour moi, mais en ajoutant use:

Pour utiliser $searchedValue, à l'intérieur de la fonction, une solution peut être use ($searchedValue) après les paramètres de la fonction function ($e) HERE.

la fonction array_filter ne renvoie que sur $neededObject le si la condition sur return est true 

Si $searchedValue est une chaîne ou un entier:

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

Si $searchedValue est un tableau où nous devons vérifier avec une liste:

$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

J'aime parfois utiliser la fonction array_reduce () pour effectuer la recherche. Semblable à array_filter () mais n’affecte pas le tableau recherché, vous permettant d’effectuer plusieurs recherches sur le même tableau d’objets.

$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): ";
}
2
yuvilio

Essayer

$entry = current(array_filter($array, function($e) use($v){ return $e->ID==$v; }));

exemple de travail ici

1
Kamil Kiełczewski

Je l'ai fait avec une sorte de keymap Java . Si vous faites cela, vous n'avez pas besoin de boucler sur votre tableau d'objets à chaque fois.

<?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'];

sortie:

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
1
Mart-Jan

Manière d'obtenir instantanément la première valeur:

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

J'ai posté ce que j'utilise pour résoudre ce problème efficacement ici en utilisant un algorithme de recherche binaire rapide: https://stackoverflow.com/a/52786742/1678210

Je ne voulais pas copier la même réponse. Quelqu'un d'autre l'avait demandé légèrement différemment mais la réponse est la même.

0
Justin Jack