PHP - bir nesne dizisinden nesne özelliğine göre giriş bul


174

Dizi şöyle görünür:

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

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

Ve tamsayı değişkenim var $v .

IDÖzelliğin $vdeğere sahip olduğu bir nesneye sahip bir dizi girişini nasıl seçebilirim ?

Yanıtlar:


189

Diziyi yineleyerek, belirli bir kaydı arar (yalnızca bir kerelik aramada ok) veya başka bir ilişkilendirilebilir dizi kullanarak bir hashmap oluşturursunuz.

İlki için böyle bir şey

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

İkincisi hakkında daha fazla bilgi için bu soruya ve müteakip yanıtlara bakın - Birden fazla dizinle referans PHP dizisi


3
$ item değerini null değerine ayarlamak gerekli değildir.
dAm2K

32
Hata! İşte aranan öğenin dizide olmaması durumunda. Alternatif olarak, kullanabilirsiniz isset($item)ama değişkenleri doğru şekilde başlatmayı tercih ediyorum
Phil

3
Anahtar değerleri dizelere ayarlanmış olanlar için kullanınif($v == $struct["ID"]){...
wbadart

67

YurkamTim haklı. Sadece bir modifikasyona ihtiyaç duyar:

($) İşlevinden sonra, "use (& $ searchedValue)" ile dış değişkene bir işaretçi gerekir ve sonra dış değişkene erişebilirsiniz. Ayrıca değiştirebilirsiniz.

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

2
Değişiklik konusunda haklısınız ve bu biraz düzgün bir yöntem, ancak hızı nesneden yinelemeye kıyasla test ettim - kendiniz, çünkü @phil'in işaret ettiği gibi, dizi_filter bunu da yapıyor - ve bu yöntem yaklaşık beş tane alıyor kat daha uzun. Test objem büyük değil, bu yüzden daha da kötüleşebilir.
Nicolai

9
&Aktarırken gerekli değildir $searchedValuekapatma kapsamı içine. Bu &, yalnızca $searchedValuekapağın içinde değiştirilmişse gerekli olan bir başvuru oluşturmak için kullanılır .
Stefan Gehrig

Çok havalı. PHP'nin böyle şeyler yapabileceğini bilmiyordum. Ben globalsadece fonksiyonları veri paylaşmak için kullanmak olduğunu düşündüm ! Ama bu gerçekten yavaşsa çok yazık. :(
NoOne

13
TS tek bir giriş istedi, bu kod bir dizi döndürür.
Pavel Vlasov

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

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

3
Bunun neden tercih edilen cevap olmadığından emin değilim. Bunun nedeni iki işlevi çağırmanız mı?
doz87

1
Ben parti için çok geç olduğunu düşünüyorum;) Herhangi bir döngü ve mola olmadan eksikliği ve okunabilirliği makul hale getirecektir. Ama henüz kıyaslama yapmadım. PHP'de bunu başarmak için birçok seçeneğiniz var.
Tim

3
Çok zarif bir çözüm. Ayrıca PHP 7'de bir dizi nesne ile çalışır. PHP 5 için: array_search ($ object-> id, array_map (function ($ object) {return $ object-> id;}, $ objects)); PHP 7 için: array_search ($ object-> id, array_column ($ objects, 'id'));
Mike

3
Bu tercih edilen cevap değildir, çünkü op bir dizi nesne ister ve bu cevap sadece saf dizileri işler.
Dwza

8
bu doğru değil. bu kod nesneleri / düz olmayan dizileri ele alır
Tim

31

Burada daha zarif bir çözüm buldum . Soruna uyarlanmış gibi görünebilir:

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

16
+1 ancak array_filterbir dizi döndürür ve bulunan ilk değerde durmaz.
Carlos Campderrós

4
$searchedValueFonksiyonun içinde tanınmıyor . Ama bunun dışında.
M. Ahmad Zafar

4
Yeni başlayanlar için bu kod $searchedValue, kapatma kapsamının dışında olduğu gibi çalışmaz . İkincisi, bu dizi yöntemlerinin nasıl çalıştığını düşünüyorsunuz? Hepsi dahili olarak dizi üzerinde döngü
Phil

1
Çoklu çekirdekler zamanında, bu - maalesef diğer programlama ortamlarında - paralel olarak işlenebilir, yukarıdaki döngü illa ki olmayabilir
FloydThreepwood

3
$searchedValuefunction ($e) use ($searchedValue) {
Need

20

Tekrar dizin oluşturmak için array_column kullanmak, birden çok kez bulmanız gerektiğinde zaman kazandırır:

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

O zaman basitçe $lookup[$id]irade yapabilirsiniz .


3
En sezgisel olmasa bile bu en şaşırtıcı cevaptı ...
Thiago Natanael

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

İstediğiniz şekilde kullanmak şöyle bir şey olurdu:

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


7

@YurkaTim'de küçük bir hatayı düzelterek , çözümünüz benim için çalışıyor, ancakuse :

Kullanmak için $searchedValue, fonksiyonun içinde, bir çözüm use ($searchedValue)fonksiyon parametrelerinden sonra olabilirfunction ($e) HERE .

array_filterişlevi yalnızca getirisi $neededObjectdönüş koşulu isetrue

Eğer $searchedValuebir dize veya tam sayıdır:

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

Eğer $searchedValuebir liste ile kontrol gerek dizidir:

$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
Bence son satır olmalı var_dump($neededObject);:)
Sliq

3

Bazen arama yapmak için array_reduce () işlevini kullanmayı seviyorum . Array_filter () işlevine benzer, ancak aranan diziyi etkilemez, böylece aynı nesne dizisinde birden çok arama yapmanızı sağlar .

$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
Koşulunuzun içinde, sonuç_dizisine eklediğiniz bir yazım hatası var. Bu olmalı:if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
adrum

Düzeltilmiş. Teşekkürler @adrum!
yuvilio

1

Bunu bir çeşit Java keymap ile yaptım. Bunu yaparsanız, nesneler dizisi üzerinde her seferinde döngü yapmanız gerekmez.

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

çıktı:

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, diziyi id ile yeniden endekslemek! Bunu yaygın olarak yapıyorum ve işleri güzelleştiriyor.
Kzqai

1

Anında ilk değeri elde etmenin yolu:

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

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.