PHP: busca la entrada por propiedad de objeto de una matriz de objetos


174

La matriz se ve así:

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

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

Y tengo una variable entera llamada $v.

¿Cómo podría seleccionar una entrada de matriz que tenga un objeto donde la IDpropiedad tenga el $vvalor?

Respuestas:


189

Puede iterar la matriz, buscar el registro particular (está bien en una búsqueda única) o construir un hashmap usando otra matriz asociativa.

Para el primero, algo como esto

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

Consulte esta pregunta y las respuestas posteriores para obtener más información sobre este último: referencia de la matriz de PHP por múltiples índices


3
No es necesario establecer $ item en nulo.
dAm2K

32
Vaya, ahí está :) Eso es en caso de que el elemento buscado no esté en la matriz. Alternativamente, podría usar, isset($item)pero prefiero inicializar las variables correctamente
Phil

3
Para aquellos de ustedes con valores clave establecidos en cadenas, useif($v == $struct["ID"]){...
wbadart

67

YurkamTim tiene razón. Solo necesita una modificación:

Después de la función ($) necesita un puntero a la variable externa mediante "use (& $ searchingValue)" y luego puede acceder a la variable externa. También puedes modificarlo.

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

2
Tiene razón sobre la modificación y es un método ordenado, pero probé la velocidad en comparación con la iteración a través del objeto, usted mismo, porque como señaló @phil, array_filter también está haciendo esto, y este método está tomando alrededor de cinco veces más largo Mi objeto de prueba no es grande, por lo que podría empeorar aún más.
Nicolai

9
No &se requiere cuando se importa $searchedValueal alcance del cierre. Se &usa para crear una referencia que solo es necesaria si $searchedValuese ha modificado dentro del cierre.
Stefan Gehrig

Eso es genial. No sabía que PHP podría hacer cosas así. ¡Pensé que usar globalera el único para compartir datos en funciones! Pero es una pena si esto es realmente lento. :(
NoOne

13
TS solicitó una sola entrada, este código devuelve una matriz.
Pavel Vlasov

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

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

3
No estoy seguro de por qué esta no es la respuesta preferida. ¿Es porque estás llamando a dos funciones?
doz87

1
Creo que llegué demasiado tarde a la fiesta;) Su escasez y legibilidad sin ningún bucle ni interrupción lo haría razonable. Pero aún no lo he evaluado. Tienes muchas opciones en PHP para lograr lo mismo.
Tim

3
Solución muy elegante. También funciona con una matriz de objetos en PHP 7. Para PHP 5: array_search ($ object-> id, array_map (function ($ object) {return $ object-> id;}, $ objects)); Para PHP 7: array_search ($ object-> id, array_column ($ objects, 'id'));
Mike

3
Esta no es la respuesta preferida porque op pide una matriz de objetos y esta respuesta solo maneja matrices puras.
Dwza

8
Eso no es correcto. este código maneja una matriz de objetos / matrices no planas
Tim

31

He encontrado una solución más elegante aquí . Adaptado a la pregunta, puede verse así:

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

16
+1 pero array_filterdevuelve una matriz y no se detendrá en el primer valor encontrado.
Carlos Campderrós

44
No se reconoce $searchedValuedentro de la función. Pero afuera está.
M. Ahmad Zafar

44
Para empezar, este código no funciona ya que $searchedValueestá fuera del alcance del cierre. En segundo lugar, ¿cómo crees que funcionan estos métodos de matriz? Todos recorren la matriz internamente
Phil

1
En el momento de los núcleos múltiples, esto, desafortunadamente en otros entornos de programación, podría procesarse en paralelo, el bucle anterior no necesariamente
FloydThreepwood

3
Para usar $searchedValuenecesita escribirfunction ($e) use ($searchedValue) {
Vilintritenmert

20

El uso de array_column para volver a indexar ahorrará tiempo si necesita buscar varias veces:

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

Entonces puedes simplemente $lookup[$id]a voluntad.


3
Esta fue la respuesta más sorprendente, incluso si no es la más intuitiva ...
Thiago Natanael

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

Usarlo como quisieras sería algo como:

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


7

Arreglando un pequeño error de @YurkaTim , su solución funciona para mí pero agrega use:

Para usar $searchedValue, dentro de la función, una solución puede ser use ($searchedValue)después de los parámetros de la función function ($e) HERE.

la array_filterfunción solo devuelve $neededObjectsi la condición de retorno estrue

Si $searchedValuees una cadena o un entero:

$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 $searchedValuees una matriz donde necesitamos verificar con una lista:

$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
Creo que la última línea debería ser var_dump($neededObject);:)
Sliq

3

A veces me gusta usar la función array_reduce () para llevar a cabo la búsqueda. Es similar a array_filter () pero no afecta la matriz buscada, lo que le permite realizar múltiples búsquedas en la misma matriz de objetos.

$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
Tiene un error tipográfico dentro de su condicional donde está agregando a la matriz de resultados. Debería ser esto:if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
Adrum

Equilibrado. Gracias @adrum!
yuvilio

1

Hice esto con algún tipo de mapa de teclas de Java. Si hace eso, no necesita recorrer su matriz de objetos cada vez.

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

salida:

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, reindexando la matriz por id! Hago esto comúnmente y hace las cosas más agradables.
Kzqai

1

Forma de obtener el primer valor al instante:

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

Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.