I have a variety of arrays that will either contain
story & message
or just
story
How would I check to see if an array contains both story and message? array_key_exists() only looks for that single key in the array.
Is there a way to do this?
Here is a solution that's scalable, even if you want to check for a large number of keys:
<?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!
}
If you only have 2 keys to check (like in the original question), it's probably easy enough to just call array_key_exists() twice to check if the keys exists.
if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
// Both keys exist.
}
However this obviously doesn't scale up well to many keys. In that situation a custom function would help.
function array_keys_exists(array $keys, array $arr) {
return !array_diff_key(array_flip($keys), $arr);
}
Surprisingly array_keys_exist doesn't exist?! In the interim that leaves some space to figure out a single line expression for this common task. I'm thinking of a shell script or another small program.
Note: each of the following solutions use concise […] array declaration syntax available in php 5.4+
array_diff + array_keys
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
// all keys found
} else {
// not all
}
(hat tip to Kim Stacks)
This approach is the most brief I've found. array_diff() returns an array of items present in argument 1 not present in argument2. Therefore an empty array indicates all keys were found. In php 5.5 you could simplify 0 === count(…) to be simply 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
}
Harder to read, easy to change. array_reduce() uses a callback to iterate over an array to arrive at a value. By feeding the keys we're interested in the $initial value of $in and then removing keys found in source we can expect to end with 0 elements if all keys were found.
The construction is easy to modify since the keys we're interested in fit nicely on the bottom line.
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
}
Simpler to write than the array_reduce solution but slightly tricker to edit. array_filter is also an iterative callback that allows you to create a filtered array by returning true (copy item to new array) or false (don't copy) in the callback. The gotchya is that you must change 2 to the number of items you expect.
This can be made more durable but verge's on preposterous readability:
$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
}
One more possible solution:
if (!array_diff(['story', 'message'], array_keys($array))) {
// OK: all the keys are in $array
} else {
// FAIL: some keys are not
}
It seems to me, that the easiest method by far would be this:
$required = array('a','b','c','d');
$values = array(
'a' => '1',
'b' => '2'
);
$missing = array_diff_key(array_flip($required), $values);
Prints:
Array(
[c] => 2
[d] => 3
)
This also allows to check which keys are missing exactly. This might be useful for error handling.
The above solutions are clever, but unnecessarily slow. A simple foreach loop over a few keys is much faster.
function array_keys_exist($keys, $array){
foreach($keys as $key){
if(!array_key_exists($key, $array)) {
return false;
}
}
return true;
}
If you have something like this:
$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');
You could simply count():
foreach ($stuff as $value) {
if (count($value) == 2) {
// story and message
} else {
// only story
}
}
This only works if you know for sure that you ONLY have these array keys, and nothing else.
Using array_key_exists() only supports checking one key at a time, so you will need to check both seperately:
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() returns true if the key is present in the array, but it is a real function and a lot to type. The language construct isset() will almost do the same, except if the tested value is NULL:
foreach ($stuff as $value) {
if (isset($value['story']) && isset($value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Additionally isset allows to check multiple variables at once:
foreach ($stuff as $value) {
if (isset($value['story'], $value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Now, to optimize the test for stuff that is set, you'd better use this "if":
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
}
}
What about this:
isset($arr['key1'], $arr['key2'])
only return true if both are not null
if is null, key is not in array
I use something like this quite often
$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0
or to find the values for the wanted keys
$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
try this
$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
}
This is the function I wrote for myself to use within a class.
<?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 />";
}
I am assuming you need to check for multiple keys ALL EXIST in an array. If you are looking for a match of at least one key, let me know so I can provide another function.
Codepad here http://codepad.viper-7.com/AKVPCH
Hope this helps:
function array_keys_exist($searchForKeys = array(), $inArray = array()) {
$inArrayKeys = array_keys($inArray);
return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys);
}
This is old and will probably get buried, but this is my attempt.
I had an issue similar to #Ryan. In some cases, I needed to only check if at least 1 key was in an array, and in some cases, all needed to be present.
So I wrote this function:
/**
* 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;
}
This was a lot easier than having to write multiple || and && blocks.
$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";
Does this not work?
array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
<?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;
}
//run demo
$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');
var_dump( check_keys_exists($key, $array));
I am not sure, if it is bad idea but I use very simple foreach loop to check multiple array key.
// 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)));
Will return true, because there are keys from $keys array in $myArray
Something as this could be used
//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;
Note the check against 2, if the values you want to search is different you can change.
This solution may not be efficient, but it works!
Updates
In one fat function:
/**
* 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)));
}
So for example with this:
$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);
Hope this helps :)
I usually use a function to validate my post and it is an answer for this question too so let me post it.
to call my function I will use the 2 array like this
validatePost(['username', 'password', 'any other field'], $_POST))
then my function will look like this
function validatePost($requiredFields, $post)
{
$validation = [];
foreach($requiredFields as $required => $key)
{
if(!array_key_exists($key, $post))
{
$validation['required'][] = $key;
}
}
return $validation;
}
this will output this
"required": [
"username",
"password",
"any other field"
]
so what this function does is validate and return all the missing fields of the post request.
// 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;
}
Related
I have a variety of arrays that will either contain
story & message
or just
story
How would I check to see if an array contains both story and message? array_key_exists() only looks for that single key in the array.
Is there a way to do this?
Here is a solution that's scalable, even if you want to check for a large number of keys:
<?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!
}
If you only have 2 keys to check (like in the original question), it's probably easy enough to just call array_key_exists() twice to check if the keys exists.
if (array_key_exists("story", $arr) && array_key_exists("message", $arr)) {
// Both keys exist.
}
However this obviously doesn't scale up well to many keys. In that situation a custom function would help.
function array_keys_exists(array $keys, array $arr) {
return !array_diff_key(array_flip($keys), $arr);
}
Surprisingly array_keys_exist doesn't exist?! In the interim that leaves some space to figure out a single line expression for this common task. I'm thinking of a shell script or another small program.
Note: each of the following solutions use concise […] array declaration syntax available in php 5.4+
array_diff + array_keys
if (0 === count(array_diff(['story', 'message', '…'], array_keys($source)))) {
// all keys found
} else {
// not all
}
(hat tip to Kim Stacks)
This approach is the most brief I've found. array_diff() returns an array of items present in argument 1 not present in argument2. Therefore an empty array indicates all keys were found. In php 5.5 you could simplify 0 === count(…) to be simply 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
}
Harder to read, easy to change. array_reduce() uses a callback to iterate over an array to arrive at a value. By feeding the keys we're interested in the $initial value of $in and then removing keys found in source we can expect to end with 0 elements if all keys were found.
The construction is easy to modify since the keys we're interested in fit nicely on the bottom line.
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
}
Simpler to write than the array_reduce solution but slightly tricker to edit. array_filter is also an iterative callback that allows you to create a filtered array by returning true (copy item to new array) or false (don't copy) in the callback. The gotchya is that you must change 2 to the number of items you expect.
This can be made more durable but verge's on preposterous readability:
$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
}
One more possible solution:
if (!array_diff(['story', 'message'], array_keys($array))) {
// OK: all the keys are in $array
} else {
// FAIL: some keys are not
}
It seems to me, that the easiest method by far would be this:
$required = array('a','b','c','d');
$values = array(
'a' => '1',
'b' => '2'
);
$missing = array_diff_key(array_flip($required), $values);
Prints:
Array(
[c] => 2
[d] => 3
)
This also allows to check which keys are missing exactly. This might be useful for error handling.
The above solutions are clever, but unnecessarily slow. A simple foreach loop over a few keys is much faster.
function array_keys_exist($keys, $array){
foreach($keys as $key){
if(!array_key_exists($key, $array)) {
return false;
}
}
return true;
}
If you have something like this:
$stuff = array();
$stuff[0] = array('story' => 'A story', 'message' => 'in a bottle');
$stuff[1] = array('story' => 'Foo');
You could simply count():
foreach ($stuff as $value) {
if (count($value) == 2) {
// story and message
} else {
// only story
}
}
This only works if you know for sure that you ONLY have these array keys, and nothing else.
Using array_key_exists() only supports checking one key at a time, so you will need to check both seperately:
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() returns true if the key is present in the array, but it is a real function and a lot to type. The language construct isset() will almost do the same, except if the tested value is NULL:
foreach ($stuff as $value) {
if (isset($value['story']) && isset($value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Additionally isset allows to check multiple variables at once:
foreach ($stuff as $value) {
if (isset($value['story'], $value['message']) {
// story and message
} else {
// either one or both keys missing
}
}
Now, to optimize the test for stuff that is set, you'd better use this "if":
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
}
}
What about this:
isset($arr['key1'], $arr['key2'])
only return true if both are not null
if is null, key is not in array
I use something like this quite often
$wantedKeys = ['story', 'message'];
$hasWantedKeys = count(array_intersect(array_keys($source), $wantedKeys)) > 0
or to find the values for the wanted keys
$wantedValues = array_intersect_key($source, array_fill_keys($wantedKeys, 1))
try this
$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
}
This is the function I wrote for myself to use within a class.
<?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 />";
}
I am assuming you need to check for multiple keys ALL EXIST in an array. If you are looking for a match of at least one key, let me know so I can provide another function.
Codepad here http://codepad.viper-7.com/AKVPCH
Hope this helps:
function array_keys_exist($searchForKeys = array(), $inArray = array()) {
$inArrayKeys = array_keys($inArray);
return count(array_intersect($searchForKeys, $inArrayKeys)) == count($searchForKeys);
}
This is old and will probably get buried, but this is my attempt.
I had an issue similar to #Ryan. In some cases, I needed to only check if at least 1 key was in an array, and in some cases, all needed to be present.
So I wrote this function:
/**
* 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;
}
This was a lot easier than having to write multiple || and && blocks.
$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";
Does this not work?
array_key_exists('story', $myarray) && array_key_exists('message', $myarray)
<?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;
}
//run demo
$key = 'a,b,c';
$array = array('a'=>'aaaa','b'=>'ccc','c'=>'eeeee');
var_dump( check_keys_exists($key, $array));
I am not sure, if it is bad idea but I use very simple foreach loop to check multiple array key.
// 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)));
Will return true, because there are keys from $keys array in $myArray
Something as this could be used
//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;
Note the check against 2, if the values you want to search is different you can change.
This solution may not be efficient, but it works!
Updates
In one fat function:
/**
* 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)));
}
So for example with this:
$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);
Hope this helps :)
I usually use a function to validate my post and it is an answer for this question too so let me post it.
to call my function I will use the 2 array like this
validatePost(['username', 'password', 'any other field'], $_POST))
then my function will look like this
function validatePost($requiredFields, $post)
{
$validation = [];
foreach($requiredFields as $required => $key)
{
if(!array_key_exists($key, $post))
{
$validation['required'][] = $key;
}
}
return $validation;
}
this will output this
"required": [
"username",
"password",
"any other field"
]
so what this function does is validate and return all the missing fields of the post request.
// 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;
}
Let’s say I have two arrays, one is of keys I require, the other is an array I want to test against.
In the array of keys I require, each key might have a value which is itself an array of keys I require, and so on.
Here’s the function so far:
static function keys_exist_in_array(Array $required_keys, Array $values_array, &$error)
{
foreach($required_keys as $key)
{
// Check required key is set in the values array
//
if (! isset($values_array[$key]))
{
// Required key is not set in the values array, set error and return
//
$error = new Error();
return false;
}
// Check the value is an array and perform function on its elements
//
if (is_array($values_array[$key]))
{
Static::keys_exist_in_array($required_keys[$key], $values_array[$key], $error);
}
return true;
}
}
My problem is that the array I want to submit to $required_keys CAN look like this:
$required_keys = array(
‘key1’,
‘key2’,
‘key3’,
‘key4’ = array(
‘key1’,
‘key2’,
‘key3’ = array(
‘key1’
)
)
);
Obviously the problem here is that foreach only finds each key, e.g. ‘key4’, rather than the values without their own value, e.g. ‘key1’, ‘key2’, ‘key3’.
But if I loop through with a standard for loop, I only get the values, key1, key2, key3.
What’s a better way of doing this?
Thanks
Several problems:
$key is the element of the array, not a key, so you
You shouldn't return false as soon as you see a non-matching element, because there could be a matching element later in the array. Instead, you should return true as soon as you find a match. Once you find a match, you don't need to keep searching.
You need to do the isarray() test first, because you'll get an error if $key is an array and you try to use $values_array[$key]. And it should be isarray($key), not isarray($values_array[$key]).
You need to test the value of the recursive call. If it succeeded, you can return immediately.
You should only return false after you finish the loop and don't find anything.
static function keys_exist_in_array(Array $required_keys, Array $values_array, &$error)
{
foreach($required_keys as $key)
{
// Check the value is an array and perform function on its elements
//
if (is_array($key))
{
$result = Static::keys_exist_in_array($required_keys[$key], $values_array[$key], $error);
if ($result) {
return true;
}
}
// Check required key is set in the values array
//
elseif (isset($values_array[$key]))
{
return true;
}
}
$error = new Error();
return false;
}
Convert the array to a key => value array with an empty value for the "keys" that don't have a value.
$arr = [
'a',
'b' => ['foo' => 1, 'bar' => 'X'],
'c' => ['baz' => 'Z'],
'd'
];
$res = [];
$keys = array_keys($arr);
$vals = array_values($arr);
foreach ($vals as $i => $v) {
if (is_array($v)) {
$res[$keys[$i]] = $v;
} else {
$res[$v] = [];
}
}
print_r($res);
Result:
Array
(
[a] => Array
(
)
[b] => Array
(
[foo] => 1
[bar] => X
)
[c] => Array
(
[baz] => Z
)
[d] => Array
(
)
)
Returning false here is the correct action if you require that ALL the $required_keys exist, because you want it to stop looking as soon as it finds a missing key.
static function keys_exist_in_array(Array $required_keys, Array $values_array, &$error)
{
foreach($required_keys as $key=>$value)
{
//check if this value is an array
if (is_array($value))
{
if (!array_key_exists($key, $values_array)
|| !Static::keys_exist_in_array($value, $values_array[$key], $error);){
$error = new Error();
return false;
}
}
// Since this value is not an array, it actually represents a
// key we need in the values array, so check if it is set
// in the values array
elseif (!array_key_exists($value, $values_array))
{
// Required key is not set in the values array, set error and return
$error = new Error();
return false;
}
}
//All elements have been found, return true
return true;
}
Using PHP, I would like to write a function that accomplishes what is shown by this pseudo code:
function return_value($input_string='array:subArray:arrayKey')
{
$segments = explode(':',$input_string);
$array_depth = count(segments) - 1;
//Now the bit I'm not sure about
//I need to dynamically generate X number of square brackets to get the value
//So that I'm left with the below:
return $array[$subArray][$arrayKey];
}
Is the above possible? I'd really appreciate some pointer on how to acheive it.
You can use a recursive function (or its iterative equivalent since it's tail recursion):
function return_value($array, $input_string) {
$segments = explode(':',$input_string);
// Can we go next step?
if (!array_key_exists($segments[0], $array)) {
return false; // cannot exist
}
// Yes, do so.
$nextlevel = $array[$segments[0]];
if (!is_array($nextlevel)) {
if (1 == count($segments)) {
// Found!
return $nextlevel;
}
// We can return $nextlevel, which is an array. Or an error.
return false;
}
array_shift($segments);
$nextsegments = implode(':', $segments);
// We can also use tail recursion here, enclosing the whole kit and kaboodle
// into a loop until $segments is empty.
return return_value($nextlevel, $nextsegments);
}
Passing one object
Let's say we want this to be an API and pass only a single string (please remember that HTTP has some method limitation in this, and you may need to POST the string instead of GET).
The string would need to contain both the array data and the "key" location. It's best if we send first the key and then the array:
function decodeJSONblob($input) {
// Step 1: extract the key address. We do this is a dirty way,
// exploiting the fact that a serialized array starts with
// a:<NUMBEROFITEMS>:{ and there will be no "{" in the key address.
$n = strpos($input, ':{');
$items = explode(':', substr($input, 0, $n));
// The last two items of $items will be "a" and "NUMBEROFITEMS"
$ni = array_pop($items);
if ("a" != ($a = array_pop($items))) {
die("Something strange at offset $n, expecting 'a', found {$a}");
}
$array = unserialize("a:{$ni}:".substr($input, $n+1));
while (!empty($items)) {
$key = array_shift($items);
if (!array_key_exists($key, $array)) {
// there is not this item in the array.
}
if (!is_array($array[$key])) {
// Error.
}
$array = $array[$key];
}
return $array;
}
$arr = array(
0 => array(
'hello' => array(
'joe','jack',
array('jill')
)));
print decodeJSONblob("0:hello:1:" . serialize($arr));
print decodeJSONblob("0:hello:2:0" . serialize($arr));
returns
jack
jill
while asking for 0:hello:2: would get you an array { 0: 'jill' }.
you could use recursion and array_key_exists to walk down to the level of said key.
function get_array_element($key, $array)
{
if(stripos(($key,':') !== FALSE) {
$currentKey = substr($key,0,stripos($key,':'));
$remainingKeys = substr($key,stripos($key,':')+1);
if(array_key_exists($currentKey,$array)) {
return ($remainingKeys,$array[$currentKey]);
}
else {
// handle error
return null;
}
}
elseif(array_key_exists($key,$array)) {
return $array[$key];
}
else {
//handle error
return null;
}
}
Use a recursive function like the following or a loop using references to array keys
<?php
function lookup($array,$lookup){
if(!is_array($lookup)){
$lookup=explode(":",$lookup);
}
$key = array_shift($lookup);
if(!isset($array[$key])){
//throw exception if key is not found so false values can also be looked up
throw new Exception("Key does not exist");
}else{
$val = $array[$key];
if(count($lookup)){
return lookup($val,$lookup);
}
return $val;
}
}
$config = array(
'db'=>array(
'host'=>'localhost',
'user'=>'user',
'pass'=>'pass'
),
'data'=>array(
'test1'=>'test1',
'test2'=>array(
'nested'=>'foo'
)
)
);
echo "Host: ".lookup($config,'db:host')."\n";
echo "User: ".lookup($config,'db:user')."\n";
echo "More levels: ".lookup($config,'data:test2:nested')."\n";
Output:
Host: localhost
User: user
More levels: foo
I have an array generated by PHP
array(
array(
'name'=>'node1',
'id' => '4'
),
array(
'name'=>'node2'
'id'=>'7'
)
)
And I am trying to add an array to a specific id (so let's say id 4)
'children'=>
array(
array('name'=>'node2','id'=>'5'),
array('name'=>'node3','id'=>'6')
)
So then it would look like
array(
array(
'name'=>'node1',
'id' => '4'
'children'=>
array(
array('name'=>'node2','id'=>'5'),
array('name'=>'node3','id'=>'6')
)
),
array(
'name'=>'node2'
'id'=>'7'
)
)
but I can't seem to figure out a way to search a multidimensional array, and add a multidimensional array to that array.
Any help?
Use a foreach loop to iterate through the array (making sure to get the key too), check the value, add if needed and break when found.
foreach($array as $k=>$v) {
if( $v['id'] == 4) {
$array[$k]['children'] = array(...);
break;
}
}
foreach($a as $k => $v)
{
if(is_array($v))
{
foreach($v as $ke => $va)
{
if($ke == 'children')
{
......
}
}
}
}
It's a monstrosity but it does what you want. Using push in a recursive function fails because the reference is destroyed after the second function call, so if you don't know how deep the key is there's a choice between using an arbitrary number of loops and hoping for the best, importing variables and using eval to push new values, or pulling apart and rebuilding the array. I chose eval. The description of what you wanted is a little different from pushing a value because you're looking for a key-value pair within an array, not an array. This function finds the key value pair and adds whatever you want as a sibling, if no value is specified the value is added as sibling to the first key matched. If no pushval is specified it will return the chain of keys that points to the matched key/key-value.
$ref_array is the multi-array to be modified,
$key is the key you're looking for,
$val is the value of the key you're looking for,
$newkey is the new key that will reference the new value,
$pushval is the new value to be indexed by $newkey.
DON'T pass an argument for the $val_array parameter. It's for use with recusive calls only. It's how the function distinguishes new calls from recursive calls, and it's how the function finds the key-value without disrupting the pass-by-reference.
function deepPush(&$ref_array, $key, $val=null, $newkey=null, $pushval=null, $val_array=null)
{
static $r, $keys;
#reset static vars on first call
if(!$val_array){ $r = 0; $keys = array();}
#cap recursion
if($r > 100){ trigger_error('Stack exceeded 100'); return;}
#init val_array
$val_array = ($r) ? $val_array : $ref_array;
#specified search value???
$search_val = ($val!==null && !in_array($val, $val_array)) ? true : false;
if(!array_key_exists($key, $val_array) || $search_val) {
$i=0;foreach($val_array as $k=>$v){
if(gettype($v) == 'array') {
if($i>0){/*dead-end*/array_pop($keys); /*keep recusion accurate*/$r-=$i;}
$keys[] = $k;/*build keychain*/
$r++; $i++; /*increment recursion, iteration*/
if(deepPush($ref_array, $key, $val, $newkey, $pushval, $v)){ /*close stack on 1st success*/return $keys;}
}//if
}//foreach
}//if
else{
if($pushval === null){return $keys;}
#add $newkey to the keychain
$keys[] = $newkey;
#process $pushval based on type
$pushval = (gettype($pushval) == 'string') ? sprintf("'%s'", $pushval) : var_export($pushval, true);
#link keys together to form pointer
$p = '$ref_array';
for($j=0,$c=count($keys); $j<$c; $j++) {
$k = $keys[$j];
$p .= "['$k']";
}//for
#concat the value to be pushed
$p .= sprintf("= %s;",$pushval);
#push it
eval($p);
$keys = array();
return true;
}//else
}
deepPush($array, 'id', 4, 'children', $addThis);
How to find if a value exists in an array and then remove it? After removing I need the sequential index order.
Are there any PHP built-in array functions for doing this?
<?php
$my_array = array('sheldon', 'leonard', 'howard', 'penny');
$to_remove = array('howard');
$result = array_diff($my_array, $to_remove);
?>
To search an element in an array, you can use array_search function and to remove an element from an array you can use unset function. Ex:
<?php
$hackers = array ('Alan Kay', 'Peter Norvig', 'Linus Trovalds', 'Larry Page');
print_r($hackers);
// Search
$pos = array_search('Linus Trovalds', $hackers);
// array_seearch returns false if an element is not found
// so we need to do a strict check here to make sure
if ($pos !== false) {
echo 'Linus Trovalds found at: ' . $pos;
// Remove from array
unset($hackers[$pos]);
}
print_r($hackers);
You can refer: https://www.php.net/manual/en/ref.array.php for more array related functions.
You need to find the key of the array first, this can be done using array_search()
Once done, use the unset()
<?php
$array = array( 'apple', 'orange', 'pear' );
unset( $array[array_search( 'orange', $array )] );
?>
Just in case you want to use any of mentioned codes, be aware that array_search returns FALSE when the "needle" is not found in "haystack" and therefore these samples would unset the first (zero-indexed) item. Use this instead:
<?php
$haystack = Array('one', 'two', 'three');
if (($key = array_search('four', $haystack)) !== FALSE) {
unset($haystack[$key]);
}
var_dump($haystack);
The above example will output:
Array
(
[0] => one
[1] => two
[2] => three
)
And that's good!
You can use array_filter to filter out elements of an array based on a callback function. The callback function takes each element of the array as an argument and you simply return false if that element should be removed. This also has the benefit of removing duplicate values since it scans the entire array.
You can use it like this:
$myArray = array('apple', 'orange', 'banana', 'plum', 'banana');
$output = array_filter($myArray, function($value) { return $value !== 'banana'; });
// content of $output after previous line:
// $output = array('apple', 'orange', 'plum');
And if you want to re-index the array, you can pass the result to array_values like this:
$output = array_values($output);
This solution is the combination of #Peter's solution for deleting multiple occurences and #chyno solution for removing first occurence. That's it what I'm using.
/**
* #param array $haystack
* #param mixed $value
* #param bool $only_first
* #return array
*/
function array_remove_values(array $haystack, $needle = null, $only_first = false)
{
if (!is_bool($only_first)) { throw new Exception("The parameter 'only_first' must have type boolean."); }
if (empty($haystack)) { return $haystack; }
if ($only_first) { // remove the first found value
if (($pos = array_search($needle, $haystack)) !== false) {
unset($haystack[$pos]);
}
} else { // remove all occurences of 'needle'
$haystack = array_diff($haystack, array($needle));
}
return $haystack;
}
Also have a look here: PHP array delete by value (not key)
The unset array_search has some pretty terrible side effects because it can accidentally strip the first element off your array regardless of the value:
// bad side effects
$a = [0,1,2,3,4,5];
unset($a[array_search(3, $a)]);
unset($a[array_search(6, $a)]);
$this->log_json($a);
// result: [1,2,4,5]
// what? where is 0?
// it was removed because false is interpreted as 0
// goodness
$b = [0,1,2,3,4,5];
$b = array_diff($b, [3,6]);
$this->log_json($b);
// result: [0,1,2,4,5]
If you know that the value is guaranteed to be in the array, go for it, but I think the array_diff is far safer. (I'm using php7)
$data_arr = array('hello', 'developer', 'laravel' );
// We Have to remove Value "hello" from the array
// Check if the value is exists in the array
if (array_search('hello', $data_arr ) !== false) {
$key = array_search('hello', $data_arr );
unset( $data_arr[$key] );
}
# output:
// It will Return unsorted Indexed array
print( $data_arr )
// To Sort Array index use this
$data_arr = array_values( $data_arr );
// Now the array key is sorted
First of all, as others mentioned, you will be using the "array_search()" & the "unset()" methodsas shown below:-
<?php
$arrayDummy = array( 'aaaa', 'bbbb', 'cccc', 'dddd', 'eeee', 'ffff', 'gggg' );
unset( $arrayDummy[array_search( 'dddd', $arrayDummy )] ); // Index 3 is getting unset here.
print_r( $arrayDummy ); // This will show the indexes as 0, 1, 2, 4, 5, 6.
?>
Now to re-index the same array, without sorting any of the array values, you will need to use the "array_values()" method as shown below:-
<?php
$arrayDummy = array_values( $arrayDummy );
print_r( $arrayDummy ); // Now, you will see the indexes as 0, 1, 2, 3, 4, 5.
?>
Hope it helps.
Okay, this is a bit longer, but does a couple of cool things.
I was trying to filter a list of emails but exclude certain domains and emails.
Script below will...
Remove any records with a certain domain
Remove any email with an exact value.
First you need an array with a list of emails and then you can add certain domains or individual email accounts to exclusion lists.
Then it will output a list of clean records at the end.
//list of domains to exclude
$excluded_domains = array(
"domain1.com",
);
//list of emails to exclude
$excluded_emails = array(
"bob#domain2.com",
"joe#domain3.com",
);
function get_domain($email) {
$domain = explode("#", $email);
$domain = $domain[1];
return $domain;
}
//loop through list of emails
foreach($emails as $email) {
//set false flag
$exclude = false;
//extract the domain from the email
$domain = get_domain($email);
//check if the domain is in the exclude domains list
if(in_array($domain, $excluded_domains)){
$exclude = true;
}
//check if the domain is in the exclude emails list
if(in_array($email, $excluded_emails)){
$exclude = true;
}
//if its not excluded add it to the final array
if($exclude == false) {
$clean_email_list[] = $email;
}
$count = $count + 1;
}
print_r($clean_email_list);
To find and remove multiple instance of value in an array, i have used the below code
$list = array(1,3,4,1,3,1,5,8);
$new_arr=array();
foreach($list as $value){
if($value=='1')
{
continue;
}
else
{
$new_arr[]=$value;
}
}
print_r($new_arr);