Как проверить, существует ли несколько ключей массива
у меня есть множество массивов, которые будут либо содержать
story & message
или просто
story
как бы я проверил, содержит ли массив историю и сообщение? array_key_exists()
ищет только один ключ в массиве.
есть ли способ сделать это?
18 ответов
Если у вас есть только 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);
}
вот решение, которое масштабируется, даже если вы хотите проверить наличие большого количества ключей:
<?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+
array_diff + array_keys
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(…)
.
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
}
труднее читать, легко изменить. array_reduce()
использует обратный вызов для итерации по массиву, чтобы прибыть по стоимости. Подавая ключи, мы заинтересованы в $initial
стоимостью $in
а затем удаление ключей, найденных в источнике, мы можем ожидать завершения с 0 элементами, если все ключи были найдены.
конструкция легка для того чтобы доработать в виду того что ключи мы заинтересованы в пригонке славно на нижней строке.
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
}
проще написать, чем array_reduce
решение, но немного сложнее редактировать. array_filter
также является итеративным обратным вызовом, который позволяет создавать отфильтрованный массив, возвращая true (копировать элемент в новый массив) или false (не копировать) в обратном вызове. В gotchya, что вы должны изменить 2
к числу элементов, которые вы ожидаете.
это можно сделать более прочным, но verge на нелепой читаемости:
$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;
}
(344ms против 768ms для 1000000 итераций)
Как насчет этого:
isset($arr['key1'], $arr['key2'])
только верните true, если оба не null
Если равно null, ключ не находится в array
если у вас есть что-то вроде этого:
$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
}
}
еще одно решение в коллекции:
if (!array_diff(['story', 'message'], array_keys($array))) {
// OK: all keys are in the $array
} else {
// FAIL: not all keys found
}
Это функция, которую я написал для себя, чтобы использовать в классе.
<?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 />";
}
Я предполагаю,что вам нужно проверить наличие нескольких ключей в массиве. Если вы ищете совпадение хотя бы одного ключа, дайте мне знать, чтобы я мог предоставить другую функцию.
Codepad здесь http://codepad.viper-7.com/AKVPCH
попробуй такое
$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
}
<?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]);
}
}
// 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;
}
$myArray = array('key1' => '', 'key2' => '');
$keys = array('key1', 'key2', 'key3');
$keyExists = count(array_intersect($keys, array_keys($myArray)));
вернет true, потому что в $myArray
что-то вроде этого можно использовать
//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);
надеюсь, что это помогает :)
надеюсь, это поможет:
function array_keys_exist($searchForKeys = array(), $inArray = array()) {
$inArrayKeys = array_keys($inArray);
return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys);
}
Это старый и, вероятно, будет похоронен, но это моя попытка.
у меня была проблема, похожая на @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;
}
Это было намного проще, чем писать несколько ||
и &&
блоки.