PHP - cari entri dengan properti objek dari array objek

174

Array terlihat seperti:

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

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

Dan saya memiliki variabel integer yang disebut $v.

Bagaimana saya bisa memilih entri array yang memiliki objek di mana IDproperti memiliki $vnilai?

Alex
sumber

Jawaban:

189

Anda bisa mengulang array, mencari catatan tertentu (ok dalam pencarian satu kali saja) atau membangun hashmap menggunakan array asosiatif lain.

Untuk yang pertama, kira-kira seperti ini

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

Lihat pertanyaan ini dan jawaban selanjutnya untuk informasi lebih lanjut tentang yang terakhir - Referensi PHP array dengan banyak indeks

Phil
sumber
3
pengaturan $ item ke null tidak diperlukan.
dAm2K
32
Ups, itu dia :) Itu kalau-kalau item yang dicari tidak ada dalam array. Atau, Anda bisa menggunakan isset($item)tetapi saya lebih suka menginisialisasi variabel dengan benar
Phil
3
Bagi Anda dengan nilai-nilai kunci diatur ke string gunakanif($v == $struct["ID"]){...
wbadart
67

YurkamTim benar. Hanya perlu modifikasi:

Setelah fungsi ($) Anda perlu pointer ke variabel eksternal dengan "gunakan (& $ searchValue)" dan kemudian Anda dapat mengakses variabel eksternal. Anda juga dapat memodifikasinya.

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use (&$searchedValue) {
        return $e->id == $searchedValue;
    }
);
Daniel Hardt
sumber
2
Anda benar tentang modifikasi dan itu adalah semacam metode yang rapi, tapi saya menguji kecepatan dibandingkan dengan iterasi melalui objek - sendiri, karena seperti @phil tunjukkan, array_filter juga melakukan ini - dan metode ini memakan waktu sekitar lima lebih lama. Objek pengujian saya bukan yang besar, sehingga mungkin bisa lebih buruk.
Nicolai
9
Tidak &diperlukan saat mengimpor $searchedValueke dalam ruang lingkup penutupan. Ini &digunakan untuk membuat referensi yang hanya diperlukan jika $searchedValuetelah dimodifikasi di dalam penutupan.
Stefan Gehrig
Itu keren. Saya tidak tahu PHP bisa melakukan hal-hal seperti itu. Saya pikir menggunakan globaladalah satu-satunya untuk berbagi data dalam fungsi! Namun sangat disayangkan jika ini memang lambat. :(
NoOne
13
TS meminta satu entri, kode ini mengembalikan array.
Pavel Vlasov
57
$arr = [
  [
    'ID' => 1
  ]
];

echo array_search(1, array_column($arr, 'ID')); // prints 0 (!== false)
Tim
sumber
3
Tidak yakin mengapa ini bukan jawaban yang disukai. Apakah karena Anda memanggil dua fungsi?
doz87
1
Saya pikir saya sudah terlambat untuk pesta;) Kekurangan dan keterbacaan tanpa loop dan istirahat akan membuatnya masuk akal. Tetapi belum membandingkannya. Anda memiliki banyak opsi dalam PHP untuk mencapai hal yang sama.
Tim
3
Solusi yang sangat elegan. Juga berfungsi dengan larik objek dalam PHP 7. Untuk PHP 5: array_search ($ objek-> id, array_map (fungsi ($ objek) {return $ objek-> id;}, $ objek)); Untuk PHP 7: array_search ($ objek-> id, array_column ($ objek, 'id'));
Mike
3
Ini bukan jawaban yang disukai karena op meminta array objek dan jawaban ini hanya menangani array murni.
Dwza
8
itu tidak benar. kode ini menangani array objek / array yang tidak rata
Tim
31

Saya telah menemukan solusi yang lebih elegan di sini . Diadaptasi untuk pertanyaan yang mungkin terlihat seperti:

$neededObject = array_filter(
    $arrayOfObjects,
    function ($e) use ($searchedValue) {
        return $e->id == $searchedValue;
    }
);
YurkaTim
sumber
16
+1 tetapi array_filtermengembalikan array, dan tidak akan berhenti pada nilai pertama yang ditemukan.
Carlos Campderrós
4
Itu tidak mengenali $searchedValuedi dalam fungsi. Tapi di luar itu.
M. Ahmad Zafar
4
Sebagai permulaan, kode ini tidak berfungsi karena $searchedValueberada di luar cakupan penutupan. Kedua, bagaimana menurut Anda metode array ini bekerja? Mereka semua mengulang array secara internal
Phil
1
Pada saat multi-core, ini - di lingkungan pemrograman lain sayangnya - dapat diproses secara paralel, loop di atas belum tentu
FloydThreepwood
3
Untuk menggunakan $searchedValueperlu menulisfunction ($e) use ($searchedValue) {
Vilintritenmert
20

Menggunakan array_column untuk mengindeks ulang akan menghemat waktu jika Anda perlu menemukan beberapa kali:

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

Maka Anda bisa $lookup[$id]sesuka hati.

Museful
sumber
3
Ini adalah jawaban yang paling menakjubkan, bahkan jika itu bukan yang paling intuitif ...
Thiago Natanael
11
class ArrayUtils
{
    public static function objArraySearch($array, $index, $value)
    {
        foreach($array as $arrayInf) {
            if($arrayInf->{$index} == $value) {
                return $arrayInf;
            }
        }
        return null;
    }
}

Menggunakannya seperti yang Anda inginkan akan menjadi seperti:

ArrayUtils::objArraySearch($array,'ID',$v);
Pablo SG Pacheco
sumber
9

Mencoba

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

contoh kerja di sini

Kamil Kiełczewski
sumber
1
Sangat bermanfaat sekali! Terima kasih kawan!
Fernando León
itu tidak akan berhenti pada elemen yang ditemukan pertama kali, bukan?
yaugenka
7

Memperbaiki kesalahan kecil dariYurkaTim , solusi Anda berfungsi untuk saya tetapi menambahkan use:

Untuk menggunakannya $searchedValue, di dalam fungsi, satu solusi bisa use ($searchedValue)setelah parameter fungsi function ($e) HERE.

satu array_filterfungsi hanya kembali pada $neededObjectjika kondisi pada kembali adalahtrue

Jika $searchedValuestring atau integer:

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

Jika $searchedValuearray di mana kita perlu memeriksa dengan daftar:

$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
Jose Carlos Ramos Carmenates
sumber
1
Saya pikir baris terakhir seharusnya var_dump($neededObject);:)
Sliq
3

Saya terkadang suka menggunakan fungsi array_reduce () untuk melakukan pencarian. Ini mirip dengan array_filter () tetapi tidak mempengaruhi array yang dicari, memungkinkan Anda untuk melakukan beberapa pencarian pada array objek yang sama.

$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): ";
}
yuvilio
sumber
1
Anda memiliki kesalahan ketik di dalam kondisi Anda di mana Anda menambahkan tot results_array. Seharusnya ini:if ($current_item->someProperty == $needle){ $result_array[] = $current_item; }
adrum
Disesuaikan. Terima kasih @rumrum!
yuvilio
1

Saya melakukan ini dengan semacam keymap Java. Jika Anda melakukannya, Anda tidak perlu mengulangi array objek Anda setiap waktu.

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

keluaran:

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
Mart-Jan
sumber
Ah, mengindeks ulang array dengan id! Saya melakukan ini secara umum dan itu membuat semuanya lebih baik.
Kzqai
1

Cara untuk langsung mendapatkan nilai pertama:

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

Saya memposting apa yang saya gunakan untuk menyelesaikan masalah ini secara efisien di sini menggunakan Algoritma Binary Search cepat: https://stackoverflow.com/a/52786742/1678210

Saya tidak ingin menyalin jawaban yang sama. Orang lain menanyakannya sedikit berbeda tetapi jawabannya sama.

Justin Jack
sumber