Bagaimana cara memeriksa apakah ada beberapa kunci array

87

Saya memiliki berbagai array yang akan berisi

story & message

atau hanya

story

Bagaimana saya memeriksa untuk melihat apakah sebuah array berisi cerita dan pesan? array_key_exists()hanya mencari kunci tunggal itu dalam larik.

Apakah ada cara untuk melakukan ini?

Ryan
sumber
2
Jika "cerita" akan ada di sana, sepertinya Anda benar-benar hanya perlu memeriksa "pesan".
Wyzard
5
Menggunakan array_intersect_key()bandingkan larik kunci yang ingin Anda verifikasi dengan larik yang Anda periksa. Jika panjang output sama dengan larik kunci yang akan diperiksa, semuanya ada.
Michael Berkowski
Wyzard, saya memiliki array lain yang berisi pesan, tapi bukan cerita, tapi mereka memiliki kunci lain yang hanya berisi array dengan cerita, atau cerita dan pesan. Terima kasih
Ryan
Apakah Anda membingungkan kunci dan nilai di sini? Apakah array diformat seperti ["story & message" => "value"]atau lebih seperti["story & message"]
GordonM

Jawaban:

72

Jika Anda hanya memiliki 2 kunci untuk diperiksa (seperti pada pertanyaan awal), mungkin cukup mudah untuk memanggil array_key_exists()dua kali untuk memeriksa apakah ada kunci.

if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
    // Both keys exist.
}

Namun ini jelas tidak berskala dengan baik untuk banyak kunci. Dalam situasi itu, fungsi kustom akan membantu.

function array_keys_exists(array $keys, array $arr) {
   return !array_diff_key(array_flip($keys), $arr);
}
alex
sumber
3
Jika orang berpikir solusi lain lebih baik untuk memeriksa apakah sebuah array memiliki dua anggota, mereka tidak boleh menyukai kode atau kinerja yang dapat dibaca dengan jelas :)
alex
Ini mungkin solusi paling sederhana jika kunci yang Anda butuhkan relatif sedikit. Jika akan menjadi tidak terbaca jika itu seperti 20 atau 30.
apokryfos
1
@apokryfos Setuju, tetapi itu menjawab pertanyaan OP.
alex
2
@alex satu-satunya masalah adalah jika $keysberisi satu elemen yang tidak$arr ada di dalamnya dan elemen lain yang ada di dalamnya, !array_diff_keymengembalikan kosong => false( contoh 3v4l ) ...
CPHPython
3
Saya pikir ini dapat dibuat lebih mudah dibaca dengan menggunakan !array_diff($keys, array_keys($array));karena ada sedikit beban kognitif yang terlibat dalam mengerjakannya array_flip.
moopet
194

Berikut adalah solusi yang dapat diskalakan, bahkan jika Anda ingin memeriksa sejumlah besar kunci:

<?php

// The values in this arrays contains the names of the indexes (keys) 
// that should exist in the data array
$required = array('key1', 'key2', 'key3');

$data = array(
    'key1' => 10,
    'key2' => 20,
    'key3' => 30,
    'key4' => 40,
);

if (count(array_intersect_key(array_flip($required), $data)) === count($required)) {
    // All required keys exist!
}
Erfan
sumber
Saya ingin tahu alasan mengapa ini diturunkan suara .. afaik ini lebih cepat karena array_intersect_key diimplementasikan di C dan Anda tidak memerlukan loop
Erfan
Cukup pintar sebenarnya, bagus - meski agak sulit dibaca.
Jon z
Terima kasih :) Anehnya PHP tidak memiliki fungsi built-in untuk melakukan ini - ini cukup umum. Ada banyak sekali kelas validasi input pengguna yang melakukan ini, tetapi untuk sebagian besar kasus penggunaan, ini berlebihan
Erfan
12
Solusi pintar memang tetapi itu benar-benar lebih lambat (sekitar 50% lebih lambat di kotak saya) daripada langsung: `` `` $ ok = true; foreach ($ diperlukan sebagai $ field) {if (! array_key_exists ($ field, $ data)) $ ok = false; }
Ozh
@Ozh selain dari array_key_exists lebih lambat dari isset
iautomation
34

Anehnya array_keys_existtidak ada ?! Untuk sementara yang menyisakan ruang untuk mencari ekspresi baris tunggal untuk tugas umum ini. Saya sedang memikirkan skrip shell atau program kecil lainnya.

Catatan: setiap solusi berikut menggunakan […]sintaks deklarasi larik ringkas yang tersedia di php 5.4+

array_diff + array_keys

if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
  // all keys found
} else {
  // not all
}

(tip topi untuk Kim Stacks )

Pendekatan ini adalah yang paling singkat yang saya temukan. array_diff()mengembalikan larik item yang ada dalam argumen 1 tidak ada dalam argumen2. Oleh karena itu, array kosong menunjukkan semua kunci ditemukan. Di php 5.5 Anda bisa menyederhanakan 0 === count(…)menjadi sederhana empty(…).

array_reduce + unset

if (0 === count(array_reduce(array_keys($source), 
    function($in, $key){ unset($in[array_search($key, $in)]); return $in; }, 
    ['story', 'message', '…'])))
{
  // all keys found
} else {
  // not all
}

Lebih sulit dibaca, mudah diubah. array_reduce()menggunakan callback untuk mengulangi larik untuk mendapatkan nilai. Dengan memberi makan kunci yang kita minati $initialnilainya $indan kemudian menghapus kunci yang ditemukan di source, kita dapat berharap untuk mengakhiri dengan 0 elemen jika semua kunci ditemukan.

Konstruksinya mudah dimodifikasi karena tombol yang kami minati pas dengan baik.

array_filter & in_array

if (2 === count(array_filter(array_keys($source), function($key) { 
        return in_array($key, ['story', 'message']); }
    )))
{
  // all keys found
} else {
  // not all
}

Lebih sederhana untuk menulis daripada array_reducesolusinya tetapi sedikit lebih sulit untuk diedit. array_filterjuga merupakan callback berulang yang memungkinkan Anda membuat array yang difilter dengan mengembalikan true (salin item ke array baru) atau false (jangan salin) di callback. Gotchya adalah Anda harus mengubah 2jumlah item yang Anda harapkan.

Ini dapat dibuat lebih tahan lama tetapi hampir pada keterbacaan yang tidak masuk akal:

$find = ['story', 'message'];
if (count($find) === count(array_filter(array_keys($source), function($key) use ($find) { return in_array($key, $find); })))
{
  // all keys found
} else {
  // not all
}
Mark Fox
sumber
3
perbedaannya akan dapat diabaikan untuk set kecil. jika Anda menulis pustaka / kerangka kerja yang menangani kumpulan data yang besar, Anda mungkin harus menguji kinerja setiap unit untuk menemukan kemacetan daripada mengoptimalkan sebelum waktunya.
Mark Fox
16

Menurut saya, metode termudah sejauh ini adalah ini:

$required = array('a','b','c','d');

$values = array(
    'a' => '1',
    'b' => '2'
);

$missing = array_diff_key(array_flip($required), $values);

Cetakan:

Array(
    [c] => 2
    [d] => 3
)

Ini juga memungkinkan untuk memeriksa kunci mana yang hilang dengan tepat. Ini mungkin berguna untuk penanganan kesalahan.

Petr Cibulka
sumber
Untuk inilah aku datang ke sini!
eNeMetcH
9

Satu lagi solusi yang mungkin:

if (!array_diff(['story', 'message'], array_keys($array))) {
    // OK: all the keys are in $array
} else {
   // FAIL: some keys are not
}
Dengan mudah
sumber
7

Solusi di atas pintar, tetapi sangat lambat. Perulangan foreach sederhana dengan isset lebih dari dua kali lebih cepat dari array_intersect_keysolusi.

function array_keys_exist($keys, $array){
    foreach($keys as $key){
        if(!array_key_exists($key, $array))return false;
    }
    return true;
}

(344ms vs 768ms untuk 1000000 iterasi)

iautomation
sumber
isset akan mengembalikan false jika ['key' => null] dan terkadang Anda memiliki array dengan nilai null. Anda harus menggunakan array_key_exists sebagai gantinya isset
j4r3k
Saya harus menggunakan yang sebaliknya di sini karena pengembalian dini dengan false( falsemenimpa truedalam kasus ini). Jadi, yang berfungsi untuk kebutuhan saya adalah Kebutuhan foreach ($keys as $key) { if (array_key_exists($key, $array)) { return true; }} return false;saya jika anykunci dalam array ada di array lain ...
Geoff
1
Saya tidak akan menyebut +/- 400ms lebih dari satu juta kunci "sangat lambat", tapi saya hanya manusia!
kolonel klik
3

Jika Anda memiliki sesuatu seperti ini:

$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');

Anda cukup count():

foreach ($stuff as $value) {
  if (count($value) == 2) {
    // story and message
  } else {
    // only story
  }
}

Ini hanya berfungsi jika Anda tahu pasti bahwa Anda HANYA memiliki kunci array ini, dan tidak ada yang lain.

Menggunakan array_key_exists () hanya mendukung pemeriksaan satu kunci pada satu waktu, jadi Anda perlu memeriksa keduanya secara terpisah:

foreach ($stuff as $value) {
  if (array_key_exists('story', $value) && array_key_exists('message', $value) {
    // story and message
  } else {
    // either one or both keys missing
  }
}

array_key_exists()mengembalikan nilai true jika kunci ada dalam array, tetapi ini adalah fungsi nyata dan banyak yang harus diketik. Konstruksi bahasa isset()akan hampir melakukan hal yang sama, kecuali jika nilai yang diuji adalah NULL:

foreach ($stuff as $value) {
  if (isset($value['story']) && isset($value['message']) {
    // story and message
  } else {
    // either one or both keys missing
  }
}

Selain itu, isset memungkinkan untuk memeriksa beberapa variabel sekaligus:

foreach ($stuff as $value) {
  if (isset($value['story'], $value['message']) {
    // story and message
  } else {
    // either one or both keys missing
  }
}

Sekarang, untuk mengoptimalkan pengujian untuk hal-hal yang disetel, Anda sebaiknya menggunakan "jika" ini:

foreach ($stuff as $value) {
  if (isset($value['story']) {
    if (isset($value['message']) {
      // story and message
    } else {
      // only story
    }
  } else {
    // No story - but message not checked
  }
}
Sven
sumber
3

Bagaimana dengan ini:

isset($arr['key1'], $arr['key2']) 

hanya mengembalikan nilai true jika keduanya bukan nol

jika null, key tidak dalam array

David Dutkovsky
sumber
1
jika nilai $arr['key1']atau $arr['key2']adalah null, kode akan, kuncinya masih ada.
Xorifelse
Saya menulis tes, silakan lihat tes @Xorifelse dan tolong perbaiki saya jika saya salah. FYI: waktu itu saya hanya tahu versi PHP 5.6. * Jadi saya lakukan hanya untuk itu.
David Dutkovsky
Apa yang coba dicapai kode itu? Mengapa Anda tidak hanya menggunakan foreachloop?
Xorifelse
Saya ingin menambahkan bukti bahwa issetfungsi berfungsi seperti yang saya maksud, tetapi sekarang saya menyadari bahwa Anda benar, kunci masih tetap berada dalam array dan oleh karena itu jawaban saya tidak benar, terima kasih atas umpan baliknya. Ya, saya bisa menggunakannya foreach.
David Dutkovsky
3

Saya sering menggunakan sesuatu seperti ini

$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0

atau untuk menemukan nilai kunci yang diinginkan

$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
Steve
sumber
2

coba ini

$required=['a','b'];$data=['a'=>1,'b'=>2];
if(count(array_intersect($required,array_keys($data))>0){
    //a key or all keys in required exist in data
 }else{
    //no keys found
  }
valmayaki
sumber
1

Ini adalah fungsi yang saya tulis untuk saya gunakan dalam kelas.

<?php
/**
 * Check the keys of an array against a list of values. Returns true if all values in the list
 is not in the array as a key. Returns false otherwise.
 *
 * @param $array Associative array with keys and values
 * @param $mustHaveKeys Array whose values contain the keys that MUST exist in $array
 * @param &$missingKeys Array. Pass by reference. An array of the missing keys in $array as string values.
 * @return Boolean. Return true only if all the values in $mustHaveKeys appear in $array as keys.
 */
    function checkIfKeysExist($array, $mustHaveKeys, &$missingKeys = array()) {
        // extract the keys of $array as an array
        $keys = array_keys($array);
        // ensure the keys we look for are unique
        $mustHaveKeys = array_unique($mustHaveKeys);
        // $missingKeys = $mustHaveKeys - $keys
        // we expect $missingKeys to be empty if all goes well
        $missingKeys = array_diff($mustHaveKeys, $keys);
        return empty($missingKeys);
    }


$arrayHasStoryAsKey = array('story' => 'some value', 'some other key' => 'some other value');
$arrayHasMessageAsKey = array('message' => 'some value', 'some other key' => 'some other value');
$arrayHasStoryMessageAsKey = array('story' => 'some value', 'message' => 'some value','some other key' => 'some other value');
$arrayHasNone = array('xxx' => 'some value', 'some other key' => 'some other value');

$keys = array('story', 'message');
if (checkIfKeysExist($arrayHasStoryAsKey, $keys)) { // return false
    echo "arrayHasStoryAsKey has all the keys<br />";
} else {
    echo "arrayHasStoryAsKey does NOT have all the keys<br />";
}

if (checkIfKeysExist($arrayHasMessageAsKey, $keys)) { // return false
    echo "arrayHasMessageAsKey has all the keys<br />";
} else {
    echo "arrayHasMessageAsKey does NOT have all the keys<br />";
}

if (checkIfKeysExist($arrayHasStoryMessageAsKey, $keys)) { // return false
    echo "arrayHasStoryMessageAsKey has all the keys<br />";
} else {
    echo "arrayHasStoryMessageAsKey does NOT have all the keys<br />";
}

if (checkIfKeysExist($arrayHasNone, $keys)) { // return false
    echo "arrayHasNone has all the keys<br />";
} else {
    echo "arrayHasNone does NOT have all the keys<br />";
}

Saya berasumsi Anda perlu memeriksa beberapa kunci SEMUA ADA dalam sebuah array. Jika Anda mencari kecocokan setidaknya satu kunci, beri tahu saya agar saya dapat memberikan fungsi lain.

Codepad di sini http://codepad.viper-7.com/AKVPCH

Kim Stacks
sumber
1
Solusinya baik-baik saja tetapi ada permata satu baris yang bagus terkubur:if (0 === count(array_diff(['key1','key2','key3'], array_keys($lookIn)))) { // all keys exist } else { // nope }
Mark Fox
Apa yang Anda tulis itu benar. Saya menemukan fungsi saya lebih mudah dibaca meskipun bertele-tele. Tentu saja, saya bisa saja salah. Terima kasih telah mengomentari jawaban saya. Saya belajar sesuatu yang baru.
Kim Stacks
1

Semoga ini membantu:

function array_keys_exist($searchForKeys = array(), $inArray = array()) {
    $inArrayKeys = array_keys($inArray);
    return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys); 
}
K-Alex
sumber
1

Ini sudah tua dan mungkin akan terkubur, tapi ini adalah usahaku.

Saya mengalami masalah yang mirip dengan @Ryan. Dalam beberapa kasus, saya perlu hanya memeriksa apakah minimal 1 utama adalah dalam array, dan dalam beberapa kasus, semua yang diperlukan untuk hadir.

Jadi saya menulis fungsi ini:

/**
 * A key check of an array of keys
 * @param array $keys_to_check An array of keys to check
 * @param array $array_to_check The array to check against
 * @param bool $strict Checks that all $keys_to_check are in $array_to_check | Default: false
 * @return bool
 */
function array_keys_exist(array $keys_to_check, array $array_to_check, $strict = false) {
    // Results to pass back //
    $results = false;

    // If all keys are expected //
    if ($strict) {
        // Strict check //

        // Keys to check count //
        $ktc = count($keys_to_check);
        // Array to check count //
        $atc = count(array_intersect($keys_to_check, array_keys($array_to_check)));

        // Compare all //
        if ($ktc === $atc) {
            $results = true;
        }
    } else {
        // Loose check - to see if some keys exist //

        // Loop through all keys to check //
        foreach ($keys_to_check as $ktc) {
            // Check if key exists in array to check //
            if (array_key_exists($ktc, $array_to_check)) {
                $results = true;
                // We found at least one, break loop //
                break;
            }
        }
    }

    return $results;
}

Ini jauh lebih mudah daripada harus menulis banyak ||dan &&blok.

Casper Wilkes
sumber
0

Apa ini tidak berhasil?

array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
Kiwi
sumber
2
Konstanta tidak dapat berupa array ... :)
Sven
Saya selalu lupa $ ketika tidak menulis kode super saya memeriksa IDE autocomplete. =)
Kiwi
0
<?php

function check_keys_exists($keys_str = "", $arr = array()){
    $return = false;
    if($keys_str != "" and !empty($arr)){
        $keys = explode(',', $keys_str);
        if(!empty($keys)){
            foreach($keys as $key){
                $return = array_key_exists($key, $arr);
                if($return == false){
                    break;
                }
            }
        }
    }
    return $return;
}

// jalankan demo

$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');

var_dump( check_keys_exists($key, $array));
Vuong
sumber
0

Saya tidak yakin, apakah itu ide yang buruk tetapi saya menggunakan foreach loop yang sangat sederhana untuk memeriksa beberapa kunci array.

// get post attachment source url
$image     = wp_get_attachment_image_src(get_post_thumbnail_id($post_id), 'single-post-thumbnail');
// read exif data
$tech_info = exif_read_data($image[0]);

// set require keys
$keys = array('Make', 'Model');

// run loop to add post metas foreach key
foreach ($keys as $key => $value)
{
    if (array_key_exists($value, $tech_info))
    {
        // add/update post meta
        update_post_meta($post_id, MPC_PREFIX . $value, $tech_info[$value]);
    }
} 
Code Lover
sumber
0
// sample data
$requiredKeys = ['key1', 'key2', 'key3'];
$arrayToValidate = ['key1' => 1, 'key2' => 2, 'key3' => 3];

function keysExist(array $requiredKeys, array $arrayToValidate) {
    if ($requiredKeys === array_keys($arrayToValidate)) {
        return true;
    }

    return false;
}
j4r3k
sumber
0
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));

Akan mengembalikan true, karena ada kunci dari array $ keys di $ myArray

Andrew Luca
sumber
0

Sesuatu seperti ini bisa digunakan

//Say given this array
$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//This gives either true or false if story and message is there
count(array_intersect(['story', 'message'], array_keys($array_in_use2))) === 2;

Perhatikan centang pada 2, jika nilai yang ingin Anda cari berbeda, Anda dapat mengubahnya.

Solusi ini mungkin tidak efisien, tetapi berhasil!

Pembaruan

Dalam satu fungsi lemak :

 /**
 * Like php array_key_exists, this instead search if (one or more) keys exists in the array
 * @param array $needles - keys to look for in the array
 * @param array $haystack - the <b>Associative</b> array to search
 * @param bool $all - [Optional] if false then checks if some keys are found
 * @return bool true if the needles are found else false. <br>
 * Note: if hastack is multidimentional only the first layer is checked<br>,
 * the needles should <b>not be<b> an associative array else it returns false<br>
 * The array to search must be associative array too else false may be returned
 */
function array_keys_exists($needles, $haystack, $all = true)
{
    $size = count($needles);
    if($all) return count(array_intersect($needles, array_keys($haystack))) === $size;
    return !empty(array_intersect($needles, array_keys($haystack)));

}

Jadi misalnya dengan ini:

$array_in_use2 = ['hay' => 'come', 'message' => 'no', 'story' => 'yes'];
//One of them exists --> true
$one_or_more_exists = array_keys_exists(['story', 'message'], $array_in_use2, false);
//all of them exists --> true
$all_exists = array_keys_exists(['story', 'message'], $array_in_use2);

Semoga ini membantu :)

Oluwatobi Samuel Omisakin
sumber
0

Saya biasanya menggunakan fungsi untuk memvalidasi posting saya dan itu adalah jawaban untuk pertanyaan ini juga jadi izinkan saya mempostingnya.

untuk memanggil fungsi saya, saya akan menggunakan 2 array seperti ini

validatePost(['username', 'password', 'any other field'], $_POST))

maka fungsi saya akan terlihat seperti ini

 function validatePost($requiredFields, $post)
    {
        $validation = [];

        foreach($requiredFields as $required => $key)
        {
            if(!array_key_exists($key, $post))
            {
                $validation['required'][] = $key;
            }
        }

        return $validation;
    }

ini akan menampilkan ini

"wajib": ["nama pengguna", "sandi", "bidang lainnya"]

jadi yang dilakukan fungsi ini adalah memvalidasi dan mengembalikan semua bidang yang hilang dari permintaan posting.

jerryurenaa
sumber
0
    $colsRequired   = ["apple", "orange", "banana", "grapes"];
    $data           = ["apple"=>"some text", "orange"=>"some text"];
    $presentInBoth  = array_intersect($colsRequired,array_keys($data));

    if( count($presentInBoth) != count($colsRequired))
        echo "Missing keys  :" . join(",",array_diff($colsRequired,$presentInBoth));
    else
        echo "All Required cols are present";
Ravi Shankar SK
sumber
Selamat datang di stackoverflow, dapatkah Anda meningkatkan jawaban Anda dengan menjelaskan sedikit dan menjelaskan kode dan menjelaskan mengapa kode ini adalah solusi.
Max Muster