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?

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


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;
    }
);

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)

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;
    }
);

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.


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);

9

Mencoba

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

contoh kerja di sini


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

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

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

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;
    }
);

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.

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.