Eu tenho uma variedade de matrizes que irão conter
story & message
ou apenas
story
Como eu verificaria se um array contém a história e a mensagem? array_key_exists()
procura apenas por aquela única chave na matriz.
Existe uma maneira de fazer isso?
array_intersect_key()
compare um array das chaves que você deseja verificar com o array que você está verificando. Se o comprimento da saída for igual ao conjunto de chaves a serem verificadas, elas estão todas presentes.["story & message" => "value"]
ou mais parecida com["story & message"]
Respostas:
Se você tiver apenas 2 chaves para verificar (como na pergunta original), provavelmente é fácil chamar
array_key_exists()
duas vezes para verificar se as chaves existem.if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) { // Both keys exist. }
No entanto, isso obviamente não se ajusta bem a muitas tonalidades. Nessa situação, uma função personalizada ajudaria.
function array_keys_exists(array $keys, array $arr) { return !array_diff_key(array_flip($keys), $arr); }
fonte
$keys
contém um elemento que não está em$arr
e outro que está nele,!array_diff_key
retorna vazio =>false
( exemplo 3v4l ) ...!array_diff($keys, array_keys($array));
porque há um pouco menos de carga cognitiva envolvida no trabalho com essesarray_flip
s.Aqui está uma solução que é escalonável, mesmo se você quiser verificar um grande número de chaves:
<?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! }
fonte
Surpreendentemente
array_keys_exist
não existe ?! Nesse ínterim, isso deixa algum espaço para descobrir uma expressão de linha única para essa tarefa comum. Estou pensando em um script de shell ou outro pequeno programa.Nota: cada uma das seguintes soluções usa
[…]
sintaxe concisa de declaração de array disponível no php 5.4+array_diff + array_keys
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) { // all keys found } else { // not all }
(gorjeta para Kim Stacks )
Essa abordagem é a mais breve que encontrei.
array_diff()
retorna uma matriz de itens presentes no argumento 1 não presentes no argumento2. Portanto, uma matriz vazia indica que todas as chaves foram encontradas. No php 5.5 você pode simplificar0 === count(…)
para ser simplesempty(…)
.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 }
Mais difícil de ler, fácil de mudar.
array_reduce()
usa um retorno de chamada para iterar em uma matriz para chegar a um valor. Ao alimentar as chaves, estamos interessados no$initial
valor de$in
e, em seguida, remover as chaves encontradas na origem, podemos esperar terminar com 0 elementos se todas as chaves forem encontradas.A construção é fácil de modificar, pois as teclas em que estamos interessados se encaixam perfeitamente no resultado final.
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 }
Mais simples de escrever do que a
array_reduce
solução, mas um pouco mais complicada de editar.array_filter
também é um retorno de chamada iterativo que permite criar uma matriz filtrada retornando verdadeiro (copiar o item para a nova matriz) ou falso (não copiar) no retorno de chamada. O ponto principal é que você deve alterar2
o número de itens que espera.Isso pode ser mais durável, mas chega a uma legibilidade absurda:
$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 }
fonte
Parece-me que o método mais fácil de longe seria este:
$required = array('a','b','c','d'); $values = array( 'a' => '1', 'b' => '2' ); $missing = array_diff_key(array_flip($required), $values);
Impressões:
Array( [c] => 2 [d] => 3 )
Isso também permite verificar quais chaves estão faltando exatamente. Isso pode ser útil para tratamento de erros.
fonte
Mais uma solução possível:
if (!array_diff(['story', 'message'], array_keys($array))) { // OK: all the keys are in $array } else { // FAIL: some keys are not }
fonte
As soluções acima são inteligentes, mas muito lentas. Um loop foreach simples com isset é duas vezes mais rápido que a
array_intersect_key
solução.function array_keys_exist($keys, $array){ foreach($keys as $key){ if(!array_key_exists($key, $array))return false; } return true; }
(344ms vs 768ms para 1.000.000 de iterações)
fonte
false
(false
substituiçõestrue
neste caso). Então, o que funciona para minhas necessidades sãoforeach ($keys as $key) { if (array_key_exists($key, $array)) { return true; }} return false;
Minhas necessidades se aany
chave em um array existe em outro array ...Se você tem algo assim:
$stuff = array(); $stuff[0] = array('story' => 'A story', 'message' => 'in a bottle'); $stuff[1] = array('story' => 'Foo');
Você poderia simplesmente
count()
:foreach ($stuff as $value) { if (count($value) == 2) { // story and message } else { // only story } }
Isso só funciona se você tiver certeza de que possui SOMENTE essas chaves de array e nada mais.
O uso de array_key_exists () suporta apenas a verificação de uma chave por vez, portanto, você precisará verificar as duas separadamente:
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()
retorna true se a chave estiver presente na matriz, mas é uma função real e muito para digitar. A construção da linguagemisset()
fará quase o mesmo, exceto se o valor testado for NULL:foreach ($stuff as $value) { if (isset($value['story']) && isset($value['message']) { // story and message } else { // either one or both keys missing } }
Além disso, o isset permite verificar várias variáveis ao mesmo tempo:
foreach ($stuff as $value) { if (isset($value['story'], $value['message']) { // story and message } else { // either one or both keys missing } }
Agora, para otimizar o teste para o que está definido, é melhor usar este "se":
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 } }
fonte
Que tal isso:
isset($arr['key1'], $arr['key2'])
só retorna verdadeiro se ambos não forem nulos
se for nulo, a chave não está na matriz
fonte
$arr['key1']
ou$arr['key2']
fornull
, o código existirá, a chave ainda existe.foreach
loop?isset
função funciona como eu pretendia, mas agora percebo que você estava certo, as chaves ainda permanecem em uma matriz e, portanto, minha resposta não está correta, obrigado pelo feedback. Sim, eu poderia usar issoforeach
.Eu uso algo assim com bastante frequência
$wantedKeys = ['story', 'message']; $hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0
ou para encontrar os valores para as chaves desejadas
$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
fonte
tente isso
$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 }
fonte
Esta é a função que escrevi para mim mesmo para usar em uma classe.
<?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 />"; }
Estou assumindo que você precisa verificar se há várias chaves TODAS EXISTENTES em uma matriz. Se você estiver procurando uma correspondência de pelo menos uma chave, me avise para que eu possa fornecer outra função.
Codepad aqui http://codepad.viper-7.com/AKVPCH
fonte
if (0 === count(array_diff(['key1','key2','key3'], array_keys($lookIn)))) { // all keys exist } else { // nope }
Espero que isto ajude:
function array_keys_exist($searchForKeys = array(), $inArray = array()) { $inArrayKeys = array_keys($inArray); return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys); }
fonte
Isso é antigo e provavelmente será enterrado, mas esta é minha tentativa.
Tive um problema semelhante ao do @Ryan. Em alguns casos, só precisei verificar se pelo menos 1 chave estava em uma matriz e, em alguns casos, todas precisavam estar presentes.
Então, escrevi esta função:
/** * 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; }
Isso foi muito mais fácil do que escrever vários blocos
||
e&&
.fonte
Isso não funciona?
array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
fonte
<?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; }
// executar demonstração
$key = 'a,b,c'; $array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee'); var_dump( check_keys_exists($key, $array));
fonte
Não tenho certeza se é uma má ideia, mas uso um loop foreach muito simples para verificar várias chaves de 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]); } }
fonte
// 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; }
fonte
$myArray = array('key1' => '', 'key2' => ''); $keys = array('key1', 'key2', 'key3'); $keyExists = count(array_intersect($keys, array_keys($myArray)));
Retornará verdadeiro, porque há chaves do array $ keys em $ myArray
fonte
Algo como isso poderia ser usado
//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;
Atualizações
Em uma função de gordura :
/** * 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))); }
Então, por exemplo com isto:
$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);
Espero que isto ajude :)
fonte
Eu costumo usar uma função para validar minha postagem e é uma resposta para essa pergunta também, então deixe-me postar.
para chamar minha função vou usar o array 2 assim
validatePost(['username', 'password', 'any other field'], $_POST))
então minha função ficará assim
function validatePost($requiredFields, $post) { $validation = []; foreach($requiredFields as $required => $key) { if(!array_key_exists($key, $post)) { $validation['required'][] = $key; } } return $validation; }
isso vai gerar isso
"obrigatório": ["nome de usuário", "senha", "qualquer outro campo"]
então o que essa função faz é validar e retornar todos os campos ausentes da solicitação de postagem.
fonte