PHP Multidimensional Array Searching (Temukan kunci dengan nilai tertentu)

114

Saya memiliki array multidimensi ini. Saya perlu mencarinya dan hanya mengembalikan kunci yang cocok dengan nilai "siput". Saya tahu ada utas lain tentang mencari array multidimensi, tetapi saya tidak benar-benar cukup memahami untuk diterapkan pada situasi saya. Terima kasih banyak atas bantuannya!

Jadi saya butuh fungsi seperti:

myfunction($products,'breville-one-touch-tea-maker-BTM800XL');
// returns 1

Inilah Array:

$products = array (
1  => array(
        'name'          => 'The Breville One-Touch Tea Maker',
        'slug'          => 'breville-one-touch-tea-maker-BTM800XL',
        'shortname'     => 'The One-Touch Tea Maker',
        'listprice'     => '299.99',
        'price'         => '249.99',
        'rating'        => '9.5',
        'reviews'       => '81',
        'buyurl'        => 'http://www.amazon.com/The-Breville-One-Touch-Tea-Maker/dp/B003LNOPSG',
        'videoref1'     => 'xNb-FOTJY1c',
        'videoref2'     => 'WAyk-O2B6F8',
        'image'         => '812BpgHhjBML.jpg',
        'related1'      => '2',
        'related2'      => '3',
        'related3'      => '4',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => 'K. Martino',
        ),

2  => array(
        'name'          => 'Breville Variable-Temperature Kettle BKE820XL',
        'slug'          => 'breville-variable-temperature-kettle-BKE820XL',
        'shortname'     => 'Variable Temperature Kettle',
        'listprice'     => '199.99',
        'price'         => '129.99',
        'rating'        => '9',
        'reviews'       => '78',
        'buyurl'        => 'http://www.amazon.com/Breville-BKE820XL-Variable-Temperature-1-8-Liter-Kettle/dp/B001DYERBK',
        'videoref1'     => 'oyZWBD83xeE',
        'image'         => '41y2B8jSKmwL.jpg',
        'related1'      => '3',
        'related2'      => '4',
        'related3'      => '5',
        'bestbuy'       => '1',
        'quote'         => '',
        'quoteautor'    => '',
        ),
);
Ben Kouba
sumber

Jawaban:

157

Sangat sederhana:

function myfunction($products, $field, $value)
{
   foreach($products as $key => $product)
   {
      if ( $product[$field] === $value )
         return $key;
   }
   return false;
}
Aurelio De Rosa
sumber
6
Jika Anda menggunakan fungsi ini dalam pernyataan bersyarat, Anda akan ingin melakukan pemeriksaan absolut terhadap jenisnya karena kunci yang dikembalikan terkadang memiliki indeks [0]. Jadi jika melakukan pemeriksaan bersyarat, akan terlihat seperti ini: if (myfunction($array, 'field', 'value') !== FALSE )) // do something...
Andy Cook
159

Solusi lain yang mungkin didasarkan pada array_search()fungsinya. Anda perlu menggunakan PHP 5.5.0 atau lebih tinggi.

Contoh

$userdb=Array
(
(0) => Array
    (
        (uid) => '100',
        (name) => 'Sandra Shush',
        (url) => 'urlof100'
    ),

(1) => Array
    (
        (uid) => '5465',
        (name) => 'Stefanie Mcmohn',
        (pic_square) => 'urlof100'
    ),

(2) => Array
    (
        (uid) => '40489',
        (name) => 'Michael',
        (pic_square) => 'urlof40489'
    )
);

$key = array_search(40489, array_column($userdb, 'uid'));

echo ("The key is: ".$key);
//This will output- The key is: 2

Penjelasan

Fungsi tersebut array_search()memiliki dua argumen. Yang pertama adalah nilai yang ingin Anda cari. Yang kedua adalah di mana fungsi harus mencari. Fungsi array_column()mendapatkan nilai dari elemen yang merupakan kuncinya 'uid'.

Ringkasan

Jadi Anda bisa menggunakannya sebagai:

array_search('breville-one-touch-tea-maker-BTM800XL', array_column($products, 'slug'));

atau, jika Anda lebih suka:

// define function
function array_search_multidim($array, $column, $key){
    return (array_search($key, array_column($array, $column)));
}

// use it
array_search_multidim($products, 'slug', 'breville-one-touch-tea-maker-BTM800XL');

Contoh asli (oleh xfoxawy) dapat ditemukan di DOCS .
The array_column() halaman .


Memperbarui

Karena komentar Vael saya penasaran, jadi saya membuat tes sederhana untuk meyakinkan kinerja metode yang digunakan array_searchdan metode yang diusulkan pada jawaban yang diterima.

Saya membuat array yang berisi 1000 array, strukturnya seperti ini (semua data diacak):

[
      {
            "_id": "57fe684fb22a07039b3f196c",
            "index": 0,
            "guid": "98dd3515-3f1e-4b89-8bb9-103b0d67e613",
            "isActive": true,
            "balance": "$2,372.04",
            "picture": "http://placehold.it/32x32",
            "age": 21,
            "eyeColor": "blue",
            "name": "Green",
            "company": "MIXERS"
      },...
]

Saya menjalankan tes pencarian 100 kali mencari nilai yang berbeda untuk bidang nama, dan kemudian saya menghitung waktu rata-rata dalam milidetik . Di sini Anda bisa melihat contohnya.

Hasilnya adalah bahwa metode yang diajukan pada jawaban ini membutuhkan sekitar 2E-7 untuk menemukan nilainya, sedangkan metode jawaban yang diterima membutuhkan sekitar 8E-7.

Seperti yang saya katakan sebelumnya, kedua waktu cukup dapat diterima untuk aplikasi yang menggunakan array dengan ukuran ini. Jika ukurannya bertambah banyak, katakanlah 1 juta elemen, maka perbedaan kecil ini juga akan bertambah.

Perbarui II

Saya telah menambahkan tes untuk metode berdasarkan array_walk_recursiveyang disebutkan di beberapa jawaban di sini. Hasil yang didapat adalah yang benar. Dan jika kita fokus pada kinerja, itu sedikit lebih buruk daripada yang diperiksa dalam tes . Dalam pengujian, Anda dapat melihat bahwa sekitar 10 kali lebih lambat daripada metode yang didasarkan array_search. Sekali lagi, ini bukan perbedaan yang sangat relevan untuk sebagian besar aplikasi.

Perbarui III

Terima kasih kepada @mickmackusa karena telah menemukan beberapa batasan pada metode ini:

  • Metode ini akan gagal pada kunci asosiatif.
  • Metode ini hanya akan bekerja pada subarray yang diindeks (mulai dari 0 dan memiliki kunci naik secara berurutan).
Iván Rodríguez Torres
sumber
Adakah yang tahu kinerja ini? Sepertinya itu pada akhirnya akan lebih lambat, dan masih membutuhkan 5,5. Saya tidak dapat menguji karena saya menggunakan 5.4.
Vael Victus
Bagi siapa saja yang tidak mengerti: di php 7, loop for lebih cepat. Ketika saya mengubah ke 5.6 dalam contoh eval.in itu, array_search sedikit lebih cepat.
Vael Victus
pintar! Saya melakukan sesuatu yang serupa, menggunakan array_combine () dengan array_column () untuk membuat array lain untuk mengambil datum saya dengan kunci yang diketahui, tetapi ini lebih elegan.
David
4
Menggunakan array_search()dengan array_column()tidak akan berfungsi pada larik sampel OP karena kunci sub larik dimulai dari 1. Metode ini juga akan gagal pada kunci asosiatif. Metode ini hanya akan bekerja pada subarray yang diindeks (mulai dari 0dan memiliki kunci naik secara berurutan). Alasannya adalah karena array_column()akan menghasilkan indeks baru dalam array yang dikembalikan.
mickmackusa
benar sekali @mickmackusa, saya telah menambahkan pengetahuan Anda pada jawabannya. Terima kasih atas bantuannya
Iván Rodríguez Torres
14

Metode kelas ini dapat mencari dalam array dengan beberapa kondisi:

class Stdlib_Array
{
    public static function multiSearch(array $array, array $pairs)
    {
        $found = array();
        foreach ($array as $aKey => $aVal) {
            $coincidences = 0;
            foreach ($pairs as $pKey => $pVal) {
                if (array_key_exists($pKey, $aVal) && $aVal[$pKey] == $pVal) {
                    $coincidences++;
                }
            }
            if ($coincidences == count($pairs)) {
                $found[$aKey] = $aVal;
            }
        }

        return $found;
    }    
}

// Example:

$data = array(
    array('foo' => 'test4', 'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test1', 'bar' => 'baz3'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz4'),
    array('foo' => 'test4', 'bar' => 'baz1'),
    array('foo' => 'test',  'bar' => 'baz1'),
    array('foo' => 'test3', 'bar' => 'baz2'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test',  'bar' => 'baz'),
    array('foo' => 'test4', 'bar' => 'baz1')
);

$result = Stdlib_Array::multiSearch($data, array('foo' => 'test4', 'bar' => 'baz1'));

var_dump($result);

Akan menghasilkan:

array(2) {
  [5]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
  [10]=>
  array(2) {
    ["foo"]=>
    string(5) "test4"
    ["bar"]=>
    string(4) "baz1"
  }
}
Fatalis
sumber
Halo Fatalist stackoverflow.com/questions/40860030/… . Terkait dengan pertanyaan ini, bisakah Anda menjelaskan pertanyaan itu
KARTHI SRV
4

Gunakan fungsi ini:

function searchThroughArray($search,array $lists){
        try{
            foreach ($lists as $key => $value) {
                if(is_array($value)){
                    array_walk_recursive($value, function($v, $k) use($search ,$key,$value,&$val){
                        if(strpos($v, $search) !== false )  $val[$key]=$value;
                    });
            }else{
                    if(strpos($value, $search) !== false )  $val[$key]=$value;
                }

            }
            return $val;

        }catch (Exception $e) {
            return false;
        }
    }

dan fungsi panggilan.

print_r(searchThroughArray('breville-one-touch-tea-maker-BTM800XL',$products));
josef
sumber
Jawaban bagus. Anda dapat memeriksa kinerja proposal Anda pada jawaban saya
Iván Rodríguez Torres
Jawaban kode-saja bernilai rendah di StackOverflow. Perbarui postingan Anda untuk menjelaskan cara kerja fungsi pencarian substring node daun. Metode ini tidak dirancang khusus untuk bekerja seperti yang diminta OP, jadi penting untuk memperjelas perbedaannya. Tautan demo akan sangat meningkatkan pemahaman pembaca. Selalu posting jawaban dengan maksud untuk mendidik OP dan audiens SO yang lebih banyak.
mickmackusa
1
function search($array, $key, $value) 
{ 
    $results = array(); 

    if (is_array($array)) 
    { 
        if (isset($array[$key]) && $array[$key] == $value) 
            $results[] = $array; 

        foreach ($array as $subarray) 
            $results = array_merge($results, search($subarray, $key, $value)); 
    } 

    return $results; 
} 
mikelee
sumber
Jawaban kode-saja bernilai rendah di StackOverflow. Harap perbarui postingan Anda untuk menjelaskan cara kerja metode rekursif, situasi yang sesuai, dan situasi di mana rekursi merupakan overhead yang tidak perlu. Selalu posting jawaban dengan maksud untuk mendidik OP dan audiens SO yang lebih banyak.
mickmackusa
1

Untuk pengunjung berikutnya yang datang: gunakan deret rekursif; itu mengunjungi setiap "daun" dalam array multidimensi. Ini untuk inspirasi:

function getMDArrayValueByKey($a, $k) {
    $r = [];
    array_walk_recursive ($a, 
                          function ($item, $key) use ($k, &$r) {if ($key == $k) $r[] = $item;}
                          );
    return $r;
}
Hans
sumber
Tidak masalah! hanya untuk menghemat waktu Anda, jika Anda mencoba jawaban josef, fungsi mengembalikan array dengan satu elemen. Kuncinya adalah jawaban yang diinginkan :)
Iván Rodríguez Torres
Jawaban @Ivan josef sangat berbeda dengan yang ini. Apakah Anda menguji ini sendiri. Saya terus mengamati jawaban ini dan saya tidak berpikir itu bisa berhasil karena array_walk_recursive tidak dapat melihat level. Untuk setiap kunci level pertama, josef memanggil strpos atau memeriksa semua leafnode. Lihat perbedaannya?
mickmackusa
Tentu saja @mickmackusa Tapi Hans memberikan semacam inspirasi, jawabannya tidak memberikan solusi secara harfiah. Ini membutuhkan lebih banyak elaborasi, seperti yang dilakukan Josef pada jawabannya. Tetapi, Anda benar pada titik bahwa jawaban ini tidak sepenuhnya mengatasi masalah.
Iván Rodríguez Torres
1

Saya akan melakukan seperti di bawah ini, di mana $productsarray sebenarnya diberikan dalam masalah di awal.

print_r(
  array_search("breville-variable-temperature-kettle-BKE820XL", 
  array_map(function($product){return $product["slug"];},$products))
);
Sam Kaz
sumber
0

Coba ini

function recursive_array_search($needle,$haystack) {
        foreach($haystack as $key=>$value) {
            $current_key=$key;
            if($needle==$value['uid'] OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
                return $current_key;
            }
        }
        return false;
    }
pawan sen
sumber
Jawaban kode-saja bernilai rendah di StackOverflow. Harap perbarui postingan Anda untuk menjelaskan cara kerja metode rekursif, situasi yang sesuai, dan situasi di mana rekursi merupakan overhead yang tidak perlu. Selalu posting jawaban dengan maksud untuk mendidik OP dan audiens SO yang lebih banyak. PS Saya pikir sebagian besar pengembang php akan lebih memilih &&dan ||daripada ANDdan ORdalam kondisi Anda. Tidak ada alasan untuk menyatakan current_key. Perbandingan $needleharus ketat.
mickmackusa