У мене є безліч масивів, які або будуть містити
story & message
або просто
story
Як перевірити, чи містить масив як історію, так і повідомлення? array_key_exists()
шукає лише той єдиний ключ у масиві.
Чи є спосіб зробити це?
У мене є безліч масивів, які або будуть містити
story & message
або просто
story
Як перевірити, чи містить масив як історію, так і повідомлення? array_key_exists()
шукає лише той єдиний ключ у масиві.
Чи є спосіб зробити це?
array_intersect_key()
порівняти масив ключів, який потрібно перевірити, із масивом, який ви перевіряєте. Якщо довжина результату збігається з масивом ключів для перевірки, вони всі присутні.
["story & message" => "value"]
чи це більше схоже["story & message"]
Відповіді:
Якщо у вас є лише 2 ключі для перевірки (як у вихідному питанні), можливо, досить просто дзвонити array_key_exists()
двічі, щоб перевірити, чи існують ключі.
if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
// Both keys exist.
}
Однак це, очевидно, погано масштабується для багатьох клавіш. У цій ситуації корисна спеціальна функція.
function array_keys_exists(array $keys, array $arr) {
return !array_diff_key(array_flip($keys), $arr);
}
$keys
містить один елемент, якого немає,$arr
а інший, що знаходиться в ньому, !array_diff_key
повертається порожнім => false
( приклад 3v4l ) ...
!array_diff($keys, array_keys($array));
оскільки когнітивне навантаження задіює трохи менше результатів array_flip
.
Ось рішення, яке масштабоване, навіть якщо ви хочете перевірити наявність великої кількості ключів:
<?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!
}
Напрочуд array_keys_exist
не існує ?! Тим часом, що залишає трохи місця, щоб зрозуміти однорядковий вираз для цього загального завдання. Я думаю про сценарій оболонки або іншу невелику програму.
Примітка: кожне з наступних рішень використовує стислий […]
синтаксис оголошення масиву, доступний у php 5.4+
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
// all keys found
} else {
// not all
}
(кінчик капелюха Кім Стек )
Цей підхід є найкоротшим, який я знайшов. array_diff()
повертає масив елементів присутніх в аргумент 1 НЕ присутній в argument2. Тому порожній масив означає, що всі ключі знайдені. У php 5.5 ви можете спростити, 0 === count(…)
щоб бути простим empty(…)
.
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
}
Важче читається, легко змінюється. array_reduce()
використовує зворотний виклик для ітерації масиву, щоб отримати значення. Подаючи ключі, які нас цікавлять $initial
значення, $in
а потім видаляючи ключі, знайдені у джерелі, ми можемо очікувати закінчення з 0 елементами, якщо всі ключі були знайдені.
Конструкцію легко модифікувати, оскільки клавіші, які нас цікавлять, добре прилягають до нижнього рядка.
if (2 === count(array_filter(array_keys($source), function($key) {
return in_array($key, ['story', 'message']); }
)))
{
// all keys found
} else {
// not all
}
Написати простіше, ніж array_reduce
рішення, але трохи хитріше редагувати. array_filter
також є ітераційним зворотним викликом, що дозволяє створити відфільтрований масив, повернувши true (скопіювати елемент у новий масив) або false (не копіювати) у зворотному виклику. Суть полягає в тому, що ви повинні змінити 2
кількість предметів, яку ви очікуєте.
Це можна зробити більш довговічним, але на межі недовірливої читабельності:
$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
}
Мені здається, що найпростішим методом був би такий:
$required = array('a','b','c','d');
$values = array(
'a' => '1',
'b' => '2'
);
$missing = array_diff_key(array_flip($required), $values);
Друк:
Array(
[c] => 2
[d] => 3
)
Це також дозволяє перевірити, яких клавіш точно не вистачає. Це може бути корисно для обробки помилок.
Вищевказані рішення розумні, але дуже повільні. Простий цикл foreach з isset є більш ніж удвічі швидшим за array_intersect_key
рішення.
function array_keys_exist($keys, $array){
foreach($keys as $key){
if(!array_key_exists($key, $array))return false;
}
return true;
}
(344 мс проти 768 мс за 1000000 ітерацій)
false
( у цьому випадку false
замінює true
). Отже, що підходить для моїх потреб, це foreach ($keys as $key) { if (array_key_exists($key, $array)) { return true; }} return false;
мої потреби, якщо any
ключ у масиві існує в іншому масиві ...
Якщо у вас є щось подібне:
$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');
Ви можете просто count()
:
foreach ($stuff as $value) {
if (count($value) == 2) {
// story and message
} else {
// only story
}
}
Це працює, лише якщо ви точно знаєте, що у вас є ТІЛЬКИ ці ключі масиву, і нічого іншого.
Використання array_key_exists () підтримує перевірку лише одного ключа за раз, тому вам потрібно буде перевірити обидва окремо:
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()
повертає true, якщо ключ присутній у масиві, але це реальна функція, яку потрібно багато ввести. Конструкція мови isset()
буде робити майже те ж саме, за винятком випадків, якщо перевіряється значення NULL:
foreach ($stuff as $value) {
if (isset($value['story']) && isset($value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Крім того, isset дозволяє одночасно перевіряти кілька змінних:
foreach ($stuff as $value) {
if (isset($value['story'], $value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Тепер, щоб оптимізувати тест для встановлених речей, краще скористайтеся цим "якщо":
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
}
}
Як що до цього:
isset($arr['key1'], $arr['key2'])
повертає true, якщо обидва значення не мають значення null
якщо має значення null, ключ відсутній у масиві
$arr['key1']
або $arr['key2']
є null
, код буде, ключ все ще існує.
foreach
цикл?
isset
функція працює, як я це мав на увазі, але тепер я усвідомлюю, що ви мали рацію, ключі все ще залишаються в масиві, і тому моя відповідь неправильна, дякую за відгук. Так, я міг би цим скористатися foreach
.
Цю функцію я написав для себе в класі.
<?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 />";
}
Я припускаю, що вам потрібно перевірити наявність декількох ключів ВСЕ ІСНУЄТЬСЯ в масиві. Якщо ви шукаєте збіг принаймні однієї клавіші, повідомте мене, щоб я міг надати іншу функцію.
Кодпад тут http://codepad.viper-7.com/AKVPCH
if (0 === count(array_diff(['key1','key2','key3'], array_keys($lookIn)))) { // all keys exist } else { // nope }
Це старо і, можливо, його поховають, але це моя спроба.
У мене була проблема, подібна до @Ryan. У деяких випадках мені потрібно було лише перевірити, чи принаймні 1 ключ міститься в масиві, а в деяких випадках всі повинні були бути присутніми.
Тому я написав цю функцію:
/**
* 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;
}
Це було набагато простіше, ніж писати декілька ||
та &&
блоки.
<?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;
}
// запустити демо
$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');
var_dump( check_keys_exists($key, $array));
Я не впевнений, що це погана ідея, але я використовую дуже простий цикл foreach для перевірки декількох ключів масиву.
// 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]);
}
}
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));
Поверне true, оскільки в $ myArray є ключі від масиву $ keys
Щось як це можна було б використати
//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;
Зверніть увагу на галочку 2, якщо значення, які потрібно шукати, відрізняються, ви можете їх змінити.
Це рішення може бути неефективним, але воно працює!
Оновлення
В одній функції жиру :
/**
* 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)));
}
Так, наприклад, з цим:
$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);
Сподіваюся, це допомагає :)
Зазвичай я використовую функцію для перевірки мого допису, і це відповідь і на це запитання, тому дозвольте мені його опублікувати.
для виклику своєї функції я буду використовувати масив 2 таким чином
validatePost(['username', 'password', 'any other field'], $_POST))
тоді моя функція буде виглядати так
function validatePost($requiredFields, $post)
{
$validation = [];
foreach($requiredFields as $required => $key)
{
if(!array_key_exists($key, $post))
{
$validation['required'][] = $key;
}
}
return $validation;
}
це виведе це
"обов'язково": ["ім'я користувача", "пароль", "будь-яке інше поле"]
тож ця функція виконує перевірку та повернення всіх відсутніх полів запиту на повідомлення.