I have an array within an array.
$a = array ( 0 => array ( 'value' => 'America', ), 1 => array ( 'value' => 'England', ), )
How do I check if 'America' exists in the array? The America array could be any key, and there could be any number of subarrays, so a generalized solution please.
Looking on the php manual I see in_array, but that only works for the top layer. so something like in_array("America", $a) would not work.
Thanks.
A general solution would be:
function deep_in_array($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && deep_in_array($needle, $element))
return true;
}
return false;
}
The reason why I chose to use in_array and a loop is: Before I examine deeper levels of the array structure, I make sure, that the searched value is not in the current level. This way, I hope the code to be faster than doing some kind of depth-first search method.
Of course if your array is always 2 dimensional and you only want to search in this kind of arrays, then this is faster:
function in_2d_array($needle, $haystack) {
foreach($haystack as $element) {
if(in_array($needle, $element))
return true;
}
return false;
}
PHP doesn't have a native array_search_recursive() function, but you can define one:
function array_search_recursive($needle, $haystack) {
foreach ($haystack as $value) {
if (is_array($value) && array_search_recursive($needle, $value)) return true;
else if ($value == $needle) return true;
}
return false;
}
Untested but you get the idea.
in_array("America", array_column($a, 'value'))
function search($a,$searchval){ //$a - array; $searchval - search value;
if(is_array($a)) {
foreach($a as $val){
if(is_array($val))
if(in_array($searchval,$val)) return true;
}
}
else return false;
}
search($a, 'America'); //function call
Related
I have an array which consists of arrays. So, now suppose I want to retrieve the sku and price whose
key value is 2=>5 and 3=>7 so it should return price=>13 and sku=>bc i.e. that array whose index is at 1 in the array.
Hi I would probably try the following (Same as Riziers comment)
foreach($array as $key => $item) {
if($item[2] == 5 && $item[3] == 7) {
// return price
return $item;
}
}
There is a function array_search, which does what you want but for simple values. You can define your own function that will take not $needle, but callable predicate:
function array_search_callback(callable $predicate, array $array)
{
foreach ($array as $key => $item) {
if ($predicate($item)) {
return $key;
}
}
return false;
}
Having this function your example can be done like this:
$key = array_search_callback(function ($item) {
return $item[2] === '5' && $item[3] === '7';
}, $array);
$result = $key === false ? null : $array[$key];
I could simply return an item from the search function. But to be consistent with the original search function, I am returning the index.
As array_search_callback takes callable as an argument you can provide any criteria you want without the need of modifying the function itself.
Here is working demo.
I am trying to build a function that allows me to find my way through a complex hierarchical structure.
For example, given this array:
$arr=array("name"=>"NameA","children"=>array());
$arr["children"][]=array("name"=>"NameB","size"=>"38");
$arr["children"][]=array("name"=>"NameC","children"=>array("name"=>'NameD',"children"=>array()));
I would like to find the complete key path to a given name. For example, a search for NameC would return $a=array('children',1) and NameD would return $a=array('children',1,'children'). This would allow me to retrieve NameD with $arr['children'][1]['children']['name'] or $arr[$a[0]][$a[1]][$a[2]]['name'].
I've experimented with calls to this function at each level:
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
$current_key=$key;
if($needle===$value OR (is_array($value) && recursive_array_search($needle,$value) !== false)) {
return $current_key;
}
}
return false;
}
But recursive_array_search('NameC') returns 'children' instead of returning 1. I've tried modifying this in multiple ways, but to no avail.
Note that I can't change the structure of the original array because I'm using this to build a JSON array that needs to have this structure.
Any help would be appreciated.
I gather path in array
function recursive_array_search($needle,$haystack) {
foreach($haystack as $key=>$value) {
// found - create array and put lower key
if($needle===$value) return(array($key));
if (is_array($value) && ($ret = recursive_array_search($needle,$value)) !== false)
// add current key as 1st item in array
{ array_unshift($ret, $key); return $ret; }
}
return false;
}
So, recursive_array_search('NameD',$arr) return:
Array (
[0] => children
[1] => 1
[2] => children
[3] => name
)
I have a method to check whether a key is in a nested associative array:
private function checkKeyIsInArray($dataItemName, $array) {
foreach ($array as $key=>$value) {
if ($key == $dataItemName) return true;
if (is_array($value)) {
checkKeyIsInArray($dataItemName, $value);
}
}
return false;
}
It always returns true, regardless of the keys I include or do not include. Here is my test array:
Array
(
[0] => Array ( [reset_time] => 2013-12-11 22:24:25 )
[1] => Array ( [email] => someone#example.com )
)
Please, what am I doing wrong? If I search for "reset_time" the method returns true (as I expect); when I search for "reset_expired" the method also returns true (which is incorrect).
Your method is almost works. But there is few issues.
Comparsion numeric values and strings. In first round method has 0 as key and 'email' as value. 0 == 'email' always returns true.
You should use $this when calling object member function.
You should return value of recursive function.
Your rewrited method.
class check
{
private function checkKeyIsInArray($dataItemName, $array)
{
foreach ($array as $key => $value)
{
// convert $key to string to prevent key type convertion
if ((string) $key == $dataItemName)
return true;
if (is_array($value))
// $this added
// return added
return $this->checkKeyIsInArray($dataItemName, $value);
}
return false;
}
public function myCheck($dataItemName, $array)
{
return $this->checkKeyIsInArray($dataItemName, $array);
}
}
$check = new check();
$array = array(array('reset_time' => 123, 'email' => 123));
var_dump($check->myCheck('reset_time', $array)); // true
var_dump($check->myCheck('reset_expired', $array)); // false
var_dump($check->myCheck('0', $array)); // true
I have updated your own code, there was some minor issue.please check.
function checkKeyIsInArray($dataItemName, $array) {
foreach ($array as $key=>$value) {
## here $key is int and $dataItemName is string so its alway comes true in ur case
if ("$key" == $dataItemName) {
return true;
}
else if (is_array($value)) {
$returnvalue=checkKeyIsInArray($dataItemName, $value);
## once a matching key found stop further recursive call
if($returnvalue==true){
return true;
}
}
}
return false;
}
Have
$my_arr_1 = array ("denied","denied","denied");
$my_arr_2 = array ("denied","denied","allowed");
Need a func that would check if all elements in the array equal to something:
in_array_all("denied",$my_arr_1); // => true
in_array_all("denied",$my_arr_2); // => false
Is there a php native function like in_array_all?
If not, what would be the most elegant way to write such a func?
function in_array_all($value, $array)
{
return (reset($array) == $value && count(array_unique($array)) == 1);
}
function in_array_all($needle,$haystack){
if(empty($needle) || empty($haystack)){
return false;
}
foreach($haystack as $k=>$v){
if($v != $needle){
return false;
}
}
return true;
}
And if you wanted to get really crazy:
function in_array_all($needle,$haystack){
if(empty($needle)){
throw new InvalidArgumentException("$needle must be a non-empty string. ".gettype($needle)." given.");
}
if(empty($haystack) || !is_array($haystack)){
throw new InvalidArgumentException("$haystack must be a non-empty array. ".gettype($haystack)." given.");
}
foreach($haystack as $k=>$v){
if($v != $needle){
return false;
}
}
return true;
}
I don't know the context of your code. But what about reversing the logic? Then you are able to use PHP's native function in_array.
$my_arr_1 = array ("denied","denied","denied");
$my_arr_2 = array ("denied","denied","allowed");
!in_array("allowed", $my_arr_1); // => true
!in_array("allowed", $my_arr_2); // => false
This entirely depends on your data set of course. But given the sample data, this would work. (Also, notice the negation ! in front of each method call to produce the desired boolean result).
Another solution using array_count_values():
function in_array_all(array $haystack, $needle) {
$count_map = array_count_values($haystack);
// in your case: [ 'denied' => 2, 'allowed' => 1 ]
return isset($count_map[$needle]) && $count_map[$needle] == count($haystack);
}
Richard's solution is best but does not have one closing paren ;-) - here is fixed and abridged:
function in_array_all($needle,$haystack)
{
if( empty($needle) || empty($haystack) ) return false;
foreach($haystack as $v)
{
if($v != $needle) return false;
}
return true;
}
I have an $array on php, and I'd like to know if the values are from a specific dictionary.
For example, if my dictionary is an array of values ['cat', 'dog', 'car', 'man'] I'd like to filter my $array and return false if a word into this one is not on the dictionary.
So, if $array is :
['men', 'cat'] // return false;
['man', 'cat'] // return true;
['cat', 'dogs'] // return false;
[''] // return false;
and so on...
How can I filter an array in this manner?
function checkDictionary($array,$dictionary){
foreach($array as $array_item){
if(!in_array($array_item,$dictionary)){
return false;
}
}
return true;
}
you can also do something like:
function checkDictionary($array,$dictionary){
$result = (empty(array_diff($array,$dictionary))) ? true : false;
return $result;
}
To increase performance, you should convert you "dictionary" to an associative array, where the keys are the words in the dictionary:
$dict = array_flip($dict);
Then all you have to do is to loop over the values you search for, which is O(n):
function contains($search, $dict) {
foreach($search as $word) {
if(!array_key_exists($word, $dict)) {
return false;
}
return true;
}
Reference: array_flip, array_key_exists
function doValuesExist($dictionary, $array) {
return (count(array_intersect($dictionary,$array)) == count($array));
}