check if array is in two multidimensional array - php

I have two multidimensional arrays:
Haystack
$haystack = array (
0 => array (
"child_element_id" => 11
"answer_id" => 15
),
1 => array (
"child_element_id" => 12
"answer_id" => 17
),
2 => array (
"child_element_id" => 13
"answer_id" => 21
)
)
Needle
$needle = array (
0 => array (
"child_element_id" => 12
"answer_id" => 17
),
1 => array (
"child_element_id" => 13
"answer_id" => 21
)
)
I want to check if all the key values from array "Needle" exists in the array "Haystack". What's the best practice for this? Thank you!

almost a solution:
#shalvah gave a good starting point. However, in the suggested solution he forgot to loop over the elements of the $needle array like shown below:
function array_in_array($neearr,$haystack) {
foreach ($neearr as $needle){
foreach ($haystack as $array) {
//check arrays for equality
if(count($needle) == count($array)) {
$needleString = serialize($needle);
$arrayString = serialize($array);
echo "$needleString||$arrayString<br>";
if(strcmp($needleString, $arrayString) == 0 ) return true;
}
return false;
}
}
}
But even so is this not completely "water tight". In cases where elements of the "needle" arrays appear in a different order (sequence) the serialze()-function will produce differing strings and will lead to false negatives, like shown in the exampe below:
$hay=array(array('a'=>'car','b'=>'bicycle'),
array('a'=>'bus','b'=>'truck'),
array('a'=>'train','b'=>'coach'));
$nee1=array(array('a'=>'car','b'=>'bicycle'),
array('a'=>'train','b'=>'coach'));
$nee2=array(array('b'=>'bicycle','a'=>'car'), // different order of elements!
array('a'=>'train','b'=>'coach'));
echo array_in_array($nee1,$hay); // true
echo array_in_array($nee2,$hay); // false (but should be true!)
a slightly better solution
This problem can be solved by first sorting (ksort(): sort by key value) all the elements of all the "needle" arrays before serialize-ing them:
function array_in_array($neearr,$haystack) {
$haystackstrarr = array_map(function($array){ksort($array);return serialize($array);},$haystack);
foreach ($neearr as $needle){
ksort($needle);
$needleString = serialize($needle);
foreach ($haystackstrarr as $arrayString){
if(strcmp($needleString, $arrayString) == 0 ) return true;
}
return false;
}
}
echo array_in_array($nee1,$hay); // true
echo array_in_array($nee2,$hay); // true

Pretty easy using in_array() since needle can be an array:
$found = 0;
foreach($needle as $array) {
if(in_array($array, $haystack, true)) {
$found++;
}
}
if($found === count($needle)) {
echo 'all needles were found in haystack';
}
Or maybe:
$found = true;
foreach($needle as $array) {
if(!in_array($array, $haystack, true)) {
$found = false;
break;
}
}
if($found) {
echo 'all needles were found in haystack';
}
You could even use array_search() as you can use an array for needle as well, no need to run two loops.
Using serialize():
if(count(array_map('unserialize',
array_intersect(array_map('serialize', $needle),
array_map('serialize',$haystack)))) == count($needle))
{
echo 'all needles were found in haystack';
}
serialize() the inner arrays of both arrays and compute the intersection (common inner arrays)
unserialize() the result and compare the count() with the count of $needle

You could use this function:
function array_in_array(array $needle, array $haystack) {
foreach($needle as $nearr) {
foreach ($haystack as $array) {
//check arrays for equality
if(count($needle) == count($array)) {
$needleString = serialize($needle);
$arrayString = serialize($array);
if(strcmp($needleString, $arrayString) == 0 )
return true;
}
}
return false;
}

Related

Trying to compare a string to an array using strpos but not working [duplicate]

I use in_array() to check whether a value exists in an array like below,
$a = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $a))
{
echo "Got Irix";
}
//print_r($a);
but what about an multidimensional array (below) - how can I check that value whether it exists in the multi-array?
$b = array(array("Mac", "NT"), array("Irix", "Linux"));
print_r($b);
or I shouldn't be using in_array() when comes to the multidimensional array?
in_array() does not work on multidimensional arrays. You could write a recursive function to do that for you:
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
Usage:
$b = array(array("Mac", "NT"), array("Irix", "Linux"));
echo in_array_r("Irix", $b) ? 'found' : 'not found';
If you know which column to search against, you can use array_search() and array_column():
$userdb = Array
(
(0) => Array
(
('uid') => '100',
('name') => 'Sandra Shush',
('url') => 'urlof100'
),
(1) => Array
(
('uid') => '5465',
('name') => 'Stefanie Mcmohn',
('url') => 'urlof5465'
),
(2) => Array
(
('uid') => '40489',
('name') => 'Michael',
('url') => 'urlof40489'
)
);
if(array_search('urlof5465', array_column($userdb, 'url')) !== false) {
echo 'value is in multidim array';
}
else {
echo 'value is not in multidim array';
}
This idea is in the comments section for array_search() on the PHP manual;
This will work too.
function in_array_r($item , $array){
return preg_match('/"'.preg_quote($item, '/').'"/i' , json_encode($array));
}
Usage:
if(in_array_r($item , $array)){
// found!
}
This will do it:
foreach($b as $value)
{
if(in_array("Irix", $value, true))
{
echo "Got Irix";
}
}
in_array only operates on a one dimensional array, so you need to loop over each sub array and run in_array on each.
As others have noted, this will only for for a 2-dimensional array. If you have more nested arrays, a recursive version would be better. See the other answers for examples of that.
$userdb = Array
(
(0) => Array
(
('uid') => '100',
('name') => 'Sandra Shush',
('url') => 'urlof100'
),
(1) => Array
(
('uid') => '5465',
('name') => 'Stefanie Mcmohn',
('url') => 'urlof5465'
),
(2) => Array
(
('uid') => '40489',
('name') => 'Michael',
('url') => 'urlof40489'
)
);
$url_in_array = in_array('urlof5465', array_column($userdb, 'url'));
if($url_in_array) {
echo 'value is in multidim array';
}
else {
echo 'value is not in multidim array';
}
if your array like this
$array = array(
array("name" => "Robert", "Age" => "22", "Place" => "TN"),
array("name" => "Henry", "Age" => "21", "Place" => "TVL")
);
Use this
function in_multiarray($elem, $array,$field)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom][$field] == $elem)
return true;
else
if(is_array($array[$bottom][$field]))
if(in_multiarray($elem, ($array[$bottom][$field])))
return true;
$bottom++;
}
return false;
}
example : echo in_multiarray("22", $array,"Age");
For Multidimensional Children: in_array('needle', array_column($arr, 'key'))
For One Dimensional Children: in_array('needle', call_user_func_array('array_merge', $arr))
Great function, but it didnt work for me until i added the if($found) { break; } to the elseif
function in_array_r($needle, $haystack) {
$found = false;
foreach ($haystack as $item) {
if ($item === $needle) {
$found = true;
break;
} elseif (is_array($item)) {
$found = in_array_r($needle, $item);
if($found) {
break;
}
}
}
return $found;
}
Since PHP 5.6 there is a better and cleaner solution for the original answer :
With a multidimensional array like this :
$a = array(array("Mac", "NT"), array("Irix", "Linux"))
We can use the splat operator :
return in_array("Irix", array_merge(...$a), true)
If you have string keys like this :
$a = array("a" => array("Mac", "NT"), "b" => array("Irix", "Linux"))
You will have to use array_values in order to avoid the error Cannot unpack array with string keys :
return in_array("Irix", array_merge(...array_values($a)), true)
You could always serialize your multi-dimensional array and do a strpos:
$arr = array(array("Mac", "NT"), array("Irix", "Linux"));
$in_arr = (bool)strpos(serialize($arr),'s:4:"Irix";');
if($in_arr){
echo "Got Irix!";
}
Various docs for things I used:
strpos()
serialize()
Type Juggling or (bool)
I believe you can just use array_key_exists nowadays:
<?php
$a=array("Mac"=>"NT","Irix"=>"Linux");
if (array_key_exists("Mac",$a))
{
echo "Key exists!";
}
else
{
echo "Key does not exist!";
}
?>
The accepted solution (at the time of writing) by jwueller
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
Is perfectly correct but may have unintended behaviuor when doing weak comparison (the parameter $strict = false).
Due to PHP's type juggling when comparing values of different type both
"example" == 0
and
0 == "example"
Evaluates true because "example" is casted to int and turned into 0.
(See Why does PHP consider 0 to be equal to a string?)
If this is not the desired behaviuor it can be convenient to cast numeric values to string before doing a non-strict comparison:
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if( ! $strict && is_string( $needle ) && ( is_float( $item ) || is_int( $item ) ) ) {
$item = (string)$item;
}
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
This is the first function of this type that I found in the php manual for in_array. Functions in the comment sections aren't always the best but if it doesn't do the trick you can look in there too :)
<?php
function in_multiarray($elem, $array)
{
// if the $array is an array or is an object
if( is_array( $array ) || is_object( $array ) )
{
// if $elem is in $array object
if( is_object( $array ) )
{
$temp_array = get_object_vars( $array );
if( in_array( $elem, $temp_array ) )
return TRUE;
}
// if $elem is in $array return true
if( is_array( $array ) && in_array( $elem, $array ) )
return TRUE;
// if $elem isn't in $array, then check foreach element
foreach( $array as $array_element )
{
// if $array_element is an array or is an object call the in_multiarray function to this element
// if in_multiarray returns TRUE, than return is in array, else check next element
if( ( is_array( $array_element ) || is_object( $array_element ) ) && $this->in_multiarray( $elem, $array_element ) )
{
return TRUE;
exit;
}
}
}
// if isn't in array return FALSE
return FALSE;
}
?>
Here is my proposition based on json_encode() solution with :
case insensitive option
returning the count instead of true
anywhere in arrays (keys and values)
If word not found, it still returns 0 equal to false.
function in_array_count($needle, $haystack, $caseSensitive = true) {
if(!$caseSensitive) {
return substr_count(strtoupper(json_encode($haystack)), strtoupper($needle));
}
return substr_count(json_encode($haystack), $needle);
}
Hope it helps.
I was looking for a function that would let me search for both strings and arrays (as needle) in the array (haystack), so I added to the answer by #jwueller.
Here's my code:
/**
* Recursive in_array function
* Searches recursively for needle in an array (haystack).
* Works with both strings and arrays as needle.
* Both needle's and haystack's keys are ignored, only values are compared.
* Note: if needle is an array, all values in needle have to be found for it to
* return true. If one value is not found, false is returned.
* #param mixed $needle The array or string to be found
* #param array $haystack The array to be searched in
* #param boolean $strict Use strict value & type validation (===) or just value
* #return boolean True if in array, false if not.
*/
function in_array_r($needle, $haystack, $strict = false) {
// array wrapper
if (is_array($needle)) {
foreach ($needle as $value) {
if (in_array_r($value, $haystack, $strict) == false) {
// an array value was not found, stop search, return false
return false;
}
}
// if the code reaches this point, all values in array have been found
return true;
}
// string handling
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle)
|| (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
I used this method works for any number of nested and not require hacking
<?php
$blogCategories = [
'programing' => [
'golang',
'php',
'ruby',
'functional' => [
'Erlang',
'Haskell'
]
],
'bd' => [
'mysql',
'sqlite'
]
];
$it = new RecursiveArrayIterator($blogCategories);
foreach (new RecursiveIteratorIterator($it) as $t) {
$found = $t == 'Haskell';
if ($found) {
break;
}
}
Please try:
in_array("irix",array_keys($b))
in_array("Linux",array_keys($b["irix"])
Im not sure about the need, but this might work for your requirement
It works too creating first a new unidimensional Array from the original one.
$arr = array("key1"=>"value1","key2"=>"value2","key3"=>"value3");
foreach ($arr as $row) $vector[] = $row['key1'];
in_array($needle,$vector);
Shorter version, for multidimensional arrays created based on database result sets.
function in_array_r($array, $field, $find){
foreach($array as $item){
if($item[$field] == $find) return true;
}
return false;
}
$is_found = in_array_r($os_list, 'os_version', 'XP');
Will return if the $os_list array contains 'XP' in the os_version field.
what about array_search? seems it quite faster than foreach according to https://gist.github.com/Ocramius/1290076 ..
if( array_search("Irix", $a) === true)
{
echo "Got Irix";
}
I found really small simple solution:
If your array is :
Array
(
[details] => Array
(
[name] => Dhruv
[salary] => 5000
)
[score] => Array
(
[ssc] => 70
[diploma] => 90
[degree] => 70
)
)
then the code will be like:
if(in_array("5000",$array['details'])){
echo "yes found.";
}
else {
echo "no not found";
}
I have found the following solution not very clean code but it works. It is used as an recursive function.
function in_array_multi( $needle, $array, $strict = false ) {
foreach( $array as $value ) { // Loop thorugh all values
// Check if value is aswell an array
if( is_array( $value )) {
// Recursive use of this function
if(in_array_multi( $needle, $value )) {
return true; // Break loop and return true
}
} else {
// Check if value is equal to needle
if( $strict === true ) {
if(strtolower($value) === strtolower($needle)) {
return true; // Break loop and return true
}
}else {
if(strtolower($value) == strtolower($needle)) {
return true; // Break loop and return true
}
}
}
}
return false; // Nothing found, false
}
Many of these searches are usually for finding things in a list of records, as some people have pointed out is really a 2-dimensional array.
This is for a list of records that have a uniform set of keys) such as a list of records grabbed from a database, among other things.
Included are both 'in_array' and 'key_exists' styled functions for this structure for completeness. Both functions return a simple true/false boolean answer.
Example 2-dimensional array of records...
$records array:
[0] => Array
(
[first_name] => Charlie
[last_name] => Brown
)
[1] => Array
(
[first_name] => Fred
[last_name] => Sanford
)
Functions:
function in_multidimensional_array($array, $column_key, $search) {
return in_array($search, array_column($array, $column_key));
}
function multidimensional_array_key_exists($array, $column_key) {
return in_array($column_key, array_keys(array_shift($array)));
}
Tests:
var_dump(in_multidimensional_array($records, 'first_name', 'Charlie')); // true
var_dump(multidimensional_array_key_exists($records, 'first_name')); // true
you can use like this
$result = array_intersect($array1, $array2);
print_r($result);
http://php.net/manual/tr/function.array-intersect.php

check whether a value exist in codeigniter result_array [duplicate]

I use in_array() to check whether a value exists in an array like below,
$a = array("Mac", "NT", "Irix", "Linux");
if (in_array("Irix", $a))
{
echo "Got Irix";
}
//print_r($a);
but what about an multidimensional array (below) - how can I check that value whether it exists in the multi-array?
$b = array(array("Mac", "NT"), array("Irix", "Linux"));
print_r($b);
or I shouldn't be using in_array() when comes to the multidimensional array?
in_array() does not work on multidimensional arrays. You could write a recursive function to do that for you:
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
Usage:
$b = array(array("Mac", "NT"), array("Irix", "Linux"));
echo in_array_r("Irix", $b) ? 'found' : 'not found';
If you know which column to search against, you can use array_search() and array_column():
$userdb = Array
(
(0) => Array
(
('uid') => '100',
('name') => 'Sandra Shush',
('url') => 'urlof100'
),
(1) => Array
(
('uid') => '5465',
('name') => 'Stefanie Mcmohn',
('url') => 'urlof5465'
),
(2) => Array
(
('uid') => '40489',
('name') => 'Michael',
('url') => 'urlof40489'
)
);
if(array_search('urlof5465', array_column($userdb, 'url')) !== false) {
echo 'value is in multidim array';
}
else {
echo 'value is not in multidim array';
}
This idea is in the comments section for array_search() on the PHP manual;
This will work too.
function in_array_r($item , $array){
return preg_match('/"'.preg_quote($item, '/').'"/i' , json_encode($array));
}
Usage:
if(in_array_r($item , $array)){
// found!
}
This will do it:
foreach($b as $value)
{
if(in_array("Irix", $value, true))
{
echo "Got Irix";
}
}
in_array only operates on a one dimensional array, so you need to loop over each sub array and run in_array on each.
As others have noted, this will only for for a 2-dimensional array. If you have more nested arrays, a recursive version would be better. See the other answers for examples of that.
$userdb = Array
(
(0) => Array
(
('uid') => '100',
('name') => 'Sandra Shush',
('url') => 'urlof100'
),
(1) => Array
(
('uid') => '5465',
('name') => 'Stefanie Mcmohn',
('url') => 'urlof5465'
),
(2) => Array
(
('uid') => '40489',
('name') => 'Michael',
('url') => 'urlof40489'
)
);
$url_in_array = in_array('urlof5465', array_column($userdb, 'url'));
if($url_in_array) {
echo 'value is in multidim array';
}
else {
echo 'value is not in multidim array';
}
if your array like this
$array = array(
array("name" => "Robert", "Age" => "22", "Place" => "TN"),
array("name" => "Henry", "Age" => "21", "Place" => "TVL")
);
Use this
function in_multiarray($elem, $array,$field)
{
$top = sizeof($array) - 1;
$bottom = 0;
while($bottom <= $top)
{
if($array[$bottom][$field] == $elem)
return true;
else
if(is_array($array[$bottom][$field]))
if(in_multiarray($elem, ($array[$bottom][$field])))
return true;
$bottom++;
}
return false;
}
example : echo in_multiarray("22", $array,"Age");
For Multidimensional Children: in_array('needle', array_column($arr, 'key'))
For One Dimensional Children: in_array('needle', call_user_func_array('array_merge', $arr))
Great function, but it didnt work for me until i added the if($found) { break; } to the elseif
function in_array_r($needle, $haystack) {
$found = false;
foreach ($haystack as $item) {
if ($item === $needle) {
$found = true;
break;
} elseif (is_array($item)) {
$found = in_array_r($needle, $item);
if($found) {
break;
}
}
}
return $found;
}
Since PHP 5.6 there is a better and cleaner solution for the original answer :
With a multidimensional array like this :
$a = array(array("Mac", "NT"), array("Irix", "Linux"))
We can use the splat operator :
return in_array("Irix", array_merge(...$a), true)
If you have string keys like this :
$a = array("a" => array("Mac", "NT"), "b" => array("Irix", "Linux"))
You will have to use array_values in order to avoid the error Cannot unpack array with string keys :
return in_array("Irix", array_merge(...array_values($a)), true)
You could always serialize your multi-dimensional array and do a strpos:
$arr = array(array("Mac", "NT"), array("Irix", "Linux"));
$in_arr = (bool)strpos(serialize($arr),'s:4:"Irix";');
if($in_arr){
echo "Got Irix!";
}
Various docs for things I used:
strpos()
serialize()
Type Juggling or (bool)
I believe you can just use array_key_exists nowadays:
<?php
$a=array("Mac"=>"NT","Irix"=>"Linux");
if (array_key_exists("Mac",$a))
{
echo "Key exists!";
}
else
{
echo "Key does not exist!";
}
?>
The accepted solution (at the time of writing) by jwueller
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
Is perfectly correct but may have unintended behaviuor when doing weak comparison (the parameter $strict = false).
Due to PHP's type juggling when comparing values of different type both
"example" == 0
and
0 == "example"
Evaluates true because "example" is casted to int and turned into 0.
(See Why does PHP consider 0 to be equal to a string?)
If this is not the desired behaviuor it can be convenient to cast numeric values to string before doing a non-strict comparison:
function in_array_r($needle, $haystack, $strict = false) {
foreach ($haystack as $item) {
if( ! $strict && is_string( $needle ) && ( is_float( $item ) || is_int( $item ) ) ) {
$item = (string)$item;
}
if (($strict ? $item === $needle : $item == $needle) || (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
This is the first function of this type that I found in the php manual for in_array. Functions in the comment sections aren't always the best but if it doesn't do the trick you can look in there too :)
<?php
function in_multiarray($elem, $array)
{
// if the $array is an array or is an object
if( is_array( $array ) || is_object( $array ) )
{
// if $elem is in $array object
if( is_object( $array ) )
{
$temp_array = get_object_vars( $array );
if( in_array( $elem, $temp_array ) )
return TRUE;
}
// if $elem is in $array return true
if( is_array( $array ) && in_array( $elem, $array ) )
return TRUE;
// if $elem isn't in $array, then check foreach element
foreach( $array as $array_element )
{
// if $array_element is an array or is an object call the in_multiarray function to this element
// if in_multiarray returns TRUE, than return is in array, else check next element
if( ( is_array( $array_element ) || is_object( $array_element ) ) && $this->in_multiarray( $elem, $array_element ) )
{
return TRUE;
exit;
}
}
}
// if isn't in array return FALSE
return FALSE;
}
?>
Here is my proposition based on json_encode() solution with :
case insensitive option
returning the count instead of true
anywhere in arrays (keys and values)
If word not found, it still returns 0 equal to false.
function in_array_count($needle, $haystack, $caseSensitive = true) {
if(!$caseSensitive) {
return substr_count(strtoupper(json_encode($haystack)), strtoupper($needle));
}
return substr_count(json_encode($haystack), $needle);
}
Hope it helps.
I was looking for a function that would let me search for both strings and arrays (as needle) in the array (haystack), so I added to the answer by #jwueller.
Here's my code:
/**
* Recursive in_array function
* Searches recursively for needle in an array (haystack).
* Works with both strings and arrays as needle.
* Both needle's and haystack's keys are ignored, only values are compared.
* Note: if needle is an array, all values in needle have to be found for it to
* return true. If one value is not found, false is returned.
* #param mixed $needle The array or string to be found
* #param array $haystack The array to be searched in
* #param boolean $strict Use strict value & type validation (===) or just value
* #return boolean True if in array, false if not.
*/
function in_array_r($needle, $haystack, $strict = false) {
// array wrapper
if (is_array($needle)) {
foreach ($needle as $value) {
if (in_array_r($value, $haystack, $strict) == false) {
// an array value was not found, stop search, return false
return false;
}
}
// if the code reaches this point, all values in array have been found
return true;
}
// string handling
foreach ($haystack as $item) {
if (($strict ? $item === $needle : $item == $needle)
|| (is_array($item) && in_array_r($needle, $item, $strict))) {
return true;
}
}
return false;
}
I used this method works for any number of nested and not require hacking
<?php
$blogCategories = [
'programing' => [
'golang',
'php',
'ruby',
'functional' => [
'Erlang',
'Haskell'
]
],
'bd' => [
'mysql',
'sqlite'
]
];
$it = new RecursiveArrayIterator($blogCategories);
foreach (new RecursiveIteratorIterator($it) as $t) {
$found = $t == 'Haskell';
if ($found) {
break;
}
}
Please try:
in_array("irix",array_keys($b))
in_array("Linux",array_keys($b["irix"])
Im not sure about the need, but this might work for your requirement
It works too creating first a new unidimensional Array from the original one.
$arr = array("key1"=>"value1","key2"=>"value2","key3"=>"value3");
foreach ($arr as $row) $vector[] = $row['key1'];
in_array($needle,$vector);
Shorter version, for multidimensional arrays created based on database result sets.
function in_array_r($array, $field, $find){
foreach($array as $item){
if($item[$field] == $find) return true;
}
return false;
}
$is_found = in_array_r($os_list, 'os_version', 'XP');
Will return if the $os_list array contains 'XP' in the os_version field.
what about array_search? seems it quite faster than foreach according to https://gist.github.com/Ocramius/1290076 ..
if( array_search("Irix", $a) === true)
{
echo "Got Irix";
}
I found really small simple solution:
If your array is :
Array
(
[details] => Array
(
[name] => Dhruv
[salary] => 5000
)
[score] => Array
(
[ssc] => 70
[diploma] => 90
[degree] => 70
)
)
then the code will be like:
if(in_array("5000",$array['details'])){
echo "yes found.";
}
else {
echo "no not found";
}
I have found the following solution not very clean code but it works. It is used as an recursive function.
function in_array_multi( $needle, $array, $strict = false ) {
foreach( $array as $value ) { // Loop thorugh all values
// Check if value is aswell an array
if( is_array( $value )) {
// Recursive use of this function
if(in_array_multi( $needle, $value )) {
return true; // Break loop and return true
}
} else {
// Check if value is equal to needle
if( $strict === true ) {
if(strtolower($value) === strtolower($needle)) {
return true; // Break loop and return true
}
}else {
if(strtolower($value) == strtolower($needle)) {
return true; // Break loop and return true
}
}
}
}
return false; // Nothing found, false
}
Many of these searches are usually for finding things in a list of records, as some people have pointed out is really a 2-dimensional array.
This is for a list of records that have a uniform set of keys) such as a list of records grabbed from a database, among other things.
Included are both 'in_array' and 'key_exists' styled functions for this structure for completeness. Both functions return a simple true/false boolean answer.
Example 2-dimensional array of records...
$records array:
[0] => Array
(
[first_name] => Charlie
[last_name] => Brown
)
[1] => Array
(
[first_name] => Fred
[last_name] => Sanford
)
Functions:
function in_multidimensional_array($array, $column_key, $search) {
return in_array($search, array_column($array, $column_key));
}
function multidimensional_array_key_exists($array, $column_key) {
return in_array($column_key, array_keys(array_shift($array)));
}
Tests:
var_dump(in_multidimensional_array($records, 'first_name', 'Charlie')); // true
var_dump(multidimensional_array_key_exists($records, 'first_name')); // true
you can use like this
$result = array_intersect($array1, $array2);
print_r($result);
http://php.net/manual/tr/function.array-intersect.php

in_array() not finding needle in haystack

I have a simple in_array statement in PHP. It's looking for the this needle:
926296884640412424_1534875699
In this haystack:
Array (
[0] => Array
(
[id] => 926296884640412424_1534875699
)
[1] => Array
(
[id] => 926301883885225094_723729160
)
)
My code is like this:
if(!in_array($object->id, $Admin->hiddenItems, true)) {
// Always fires
} else {
// Never fires
}
And it never finds it. I've tried both with strict set to TRUE and FALSE, but neither works.
What am I doing wrong?
You're searching in a multidimensional array. Flatten it before using in_array():
if (!in_array($object->id, array_column($Admin->hiddenItems, 'id'), true)) {
...
}
<?php
$arrays = array(
array(
'id' => '926296884640412424_1534875699'
),
array(
'id' => '926301883885225094_723729160'
)
);
print exist('926296884640412424_1534875699', $arrays);
function exist($id, $arrays) {
foreach ($arrays as $array) {
if (in_array($id, $array)) {
return "exist";
}
}
return "no exist";
}
You can use this recursive function as well to search certain value in multidimensional arrays:
function multi_in_array_r($needle, $haystack) {
if(in_array($needle, $haystack)) {
return true;
}
foreach($haystack as $element) {
if(is_array($element) && multi_in_array_r($needle, $element))
return true;
}
return false;
}
It's up to you to decide what gives best results, because as you can see there are few different way to accomplish the same thing.

Check if specific array key exists in multidimensional array - PHP

I have a multidimensional array e.g. (this can be many levels deep):
$array = Array (
[21] => Array ( )
[24] => Array (
[22] => Array ( )
[25] => Array (
[26] => Array ( )
)
)
)
I am trying to loop through it to see if a certain key exists:
$keySearch = 22; // key searching for
function findKey($array, $keySearch) {
foreach ($array as $item){
if (isset($item[$keySearch]) && false === findKey($item[$keySearch], $item)){
echo 'yes, it exists';
}
}
}
findKey($array, $keySearch);
But it finds nothing. Is there an error in the loop?
array_key_exists() is helpful.
Then something like this:
function multiKeyExists(array $arr, $key) {
// is in base array?
if (array_key_exists($key, $arr)) {
return true;
}
// check arrays contained in this array
foreach ($arr as $element) {
if (is_array($element)) {
if (multiKeyExists($element, $key)) {
return true;
}
}
}
return false;
}
Working example: http://codepad.org/GU0qG5su
I played with your code to get it working :
function findKey($array, $keySearch)
{
foreach ($array as $key => $item) {
if ($key == $keySearch) {
echo 'yes, it exists';
return true;
} elseif (is_array($item) && findKey($item, $keySearch)) {
return true;
}
}
return false;
}
Here is a one line solution:
echo strpos(json_encode($array), $key) > 0 ? "found" : "not found";
This converts the array to a string containing the JSON equivalent, then it uses that string as the haystack argument of the strpos() function and it uses $key as the needle argument ($key is the value to find in the JSON string).
It can be helpful to do this to see the converted string: echo json_encode($array);
Be sure to enclose the needle argument in single quotes then double quotes because the name portion of the name/value pair in the JSON string will appear with double quotes around it. For instance, if looking for 22 in the array below then $key = '"22"' will give the correct result of not found in this array:
$array =
Array (
21 => Array ( ),
24 =>
Array (
522 => Array ( ),
25 =>
Array (
26 => Array ( )
)
)
);
However, if the single quotes are left off, as in $key = "22" then an incorrect result of found will result for the array above.
EDIT: A further improvement would be to search for $key = '"22":'; just incase a value of "22" exists in the array. ie. 27 => "22" In addition, this approach is not bullet proof. An incorrect found could result if any of the array's values contain the string '"22":'
function findKey($array, $keySearch)
{
// check if it's even an array
if (!is_array($array)) return false;
// key exists
if (array_key_exists($keySearch, $array)) return true;
// key isn't in this array, go deeper
foreach($array as $key => $val)
{
// return true if it's found
if (findKey($val, $keySearch)) return true;
}
return false;
}
// test
$array = Array (
21 => Array ( 24 => 'ok' ),
24 => Array (
22 => Array ( 29 => 'ok' ),
25 => Array (
26 => Array ( 32 => 'ok' )
)
)
);
$findKeys = Array(21, 22, 23, 24, 25, 26, 27, 28, 29, 30);
foreach ($findKeys as $key)
{
echo (findKey($array, $key)) ? 'found ' : 'not found ';
echo $key.'<br>';
}
returns false if doesn't exists, returns the first instance if does;
function searchArray( array $array, $search )
{
while( $array ) {
if( isset( $array[ $search ] ) ) return $array[ $search ];
$segment = array_shift( $array );
if( is_array( $segment ) ) {
if( $return = searchArray( $segment, $search ) ) return $return;
}
}
}
return false;
}
For sure some errors, is this roughly what you are after? (Untested code):
$keySearch=22; // key seraching for
function findKey($array, $keySearch)
{
// check whether input is an array
if(is_array($array)
{
foreach ($array as $item)
{
if (isset($item[$keySearch]) || findKey($item, $keysearch) === true)
{
echo 'yes, it exists';
return true;
}
}
}
}
Here is one solution that finds and return the value of the key in any dimension array..
function findValByKey($arr , $keySearch){
$out = null;
if (is_array($arr)){
if (array_key_exists($keySearch, $arr)){
$out = $arr[$keySearch];
}else{
foreach ($arr as $key => $value){
if ($out = self::findValByKey($value, $keySearch)){
break;
}
}
}
}
return $out;
}
I did modified to return value of searched key:
function findKeyInArray($array, $keySearch, &$value)
{
foreach ($array as $key => $item) {
if ($key === $keySearch) {
$value = $item;
break;
} elseif (is_array($item)) {
findKeyInArray($item, $keySearch,$value);
}
}
}
$timeZone = null;
findKeyInArray($request, 'timezone', $timeZone);

Count "truthy" values in a 2d array

Given the following array $mm
Array
(
[147] => Array
(
[pts_m] =>
[pts_mreg] => 1
[pts_cg] => 1
)
[158] => Array
(
[pts_m] =>
[pts_mreg] =>
[pts_cg] => 0
)
[159] => Array
(
[pts_m] =>
[pts_mreg] => 1
[pts_cg] => 1
)
)
When I run count(array_filter($mm)) I get 3 as result since it is not recursive.
count(array_filter($mm), COUNT_RECURSIVE) also will not do because I actually need to run the array_filter recursively, and then count its result.
So my question is: how do I recursively run array_filter($mm) in this case?
My expected result here would be 4.
Please note that I am not using any callback so I can exclude false, null and empty.
From the PHP array_filter documentation:
//This function filters an array and remove all null values recursively.
<?php
function array_filter_recursive($input)
{
foreach ($input as &$value)
{
if (is_array($value))
{
$value = array_filter_recursive($value);
}
}
return array_filter($input);
}
?>
//Or with callback parameter (not tested) :
<?php
function array_filter_recursive($input, $callback = null)
{
foreach ($input as &$value)
{
if (is_array($value))
{
$value = array_filter_recursive($value, $callback);
}
}
return array_filter($input, $callback);
}
?>
Should work
$count = array_sum(array_map(function ($item) {
return ((int) !is_null($item['pts_m'])
+ ((int) !is_null($item['pts_mreg'])
+ ((int) !is_null($item['pts_cg']);
}, $array);
or maybe
$count = array_sum(array_map(function ($item) {
return array_sum(array_map('is_int', $item));
}, $array);
There are definitely many more possible solutions. If you want to use array_filter() (without callback) remember, that it treats 0 as false too and therefore it will remove any 0-value from the array.
If you are using PHP in a pre-5.3 version, I would use a foreach-loop
$count = 0;
foreach ($array as $item) {
$count += ((int) !is_null($item['pts_m'])
+ ((int) !is_null($item['pts_mreg'])
+ ((int) !is_null($item['pts_cg']);
}
Update
Regarding the comment below:
Thx #kc I actually want the method to remove false, 0, empty etc
When this is really only, what you want, the solution is very simple too.
But now I don't know, how to interpret
My expected result here would be 5.
Anyway, its short now :)
$result = array_map('array_filter', $array);
$count = array_map('count', $result);
$countSum = array_sum($count);
The resulting array looks like
Array
(
[147] => Array
(
[pts_mreg] => 1
[pts_cg] => 1
)
[158] => Array
(
)
[159] => Array
(
[pts_mreg] => 1
[pts_cg] => 1
)
)
A better alternative
One implementation that always worked for me is this one:
function filter_me(&$array) {
foreach ( $array as $key => $item ) {
is_array ( $item ) && $array [$key] = filter_me ( $item );
if (empty ( $array [$key] ))
unset ( $array [$key] );
}
return $array;
}
I notice that someone had created a similar function except that this one presents, in my opinion, few advantages:
you pass an array as reference (not its copy) and thus the algorithm is memory-friendly
no additional calls to array_filter which in reality involves:
the use of stack, ie. additional memory
some other operations, ie. CPU cycles
Benchmarks
A 64MB array
filter_me function finished in 0.8s AND the PHP allocated memory before starting the function was 65MB, when function returned it was 39.35MB !!!
array_filter_recursive function recommended above by Francois Deschenes had no chance; after 1s PHP Fatal error: Allowed memory size of 134217728 bytes exhausted
A 36MB array
filter_me function finished in 0.4s AND the PHP allocated memory before starting the function was 36.8MB, when function returned it was 15MB !!!
array_filter_recursive function succeeded this time in 0.6s and memory before/after was quite the same
I hope it helps.
This function effectively applies filter_recursive with a provided callback
class Arr {
public static function filter_recursive($array, $callback = NULL)
{
foreach ($array as $index => $value)
{
if (is_array($value))
{
$array[$index] = Arr::filter_recursive($value, $callback);
}
else
{
$array[$index] = call_user_func($callback, $value);
}
if ( ! $array[$index])
{
unset($array[$index]);
}
}
return $array;
}
}
And you'd use it this way:
Arr::filter_recursive($my_array, $my_callback);
This might help someone
I needed an array filter recursive function that would walk through all nodes (including arrays, so that we have the possibility to discard entire arrays), and so I came up with this:
public static function filterRecursive(array $array, callable $callback): array
{
foreach ($array as $k => $v) {
$res = call_user_func($callback, $v);
if (false === $res) {
unset($array[$k]);
} else {
if (is_array($v)) {
$array[$k] = self::filterRecursive($v, $callback);
}
}
}
return $array;
}
See more examples here: https://github.com/lingtalfi/Bat/blob/master/ArrayTool.md#filterrecursive
This should work for callback and mode support along with an optional support for depth.
function array_filter_recursive(array $array, callable $callback = null, int $mode = 0, int $depth = -1): array
{
foreach ($array as & $value) {
if ($depth != 0 && is_array($value)) {
$value = array_filter_recursive($value, $callback, $mode, $depth - 1);
}
}
if ($callback) {
return array_filter($array, $callback, $mode);
}
return array_filter($array);
}
Calling the function with $depth = 0 for nested arrays, will yield the same result as array_filter.
This strike me as an XY Problem.
Recursion is not necessary because the array has a consistent depth of 2 levels.
It is not necessary to generate an array of filtered elements so that you can traverse the filtered data to count it. Just traverse once and add 1 to the count variable whenever a truthy value is encountered.
The following snippet calls no functions (only language constructs -- foreach()) and therefore will be highly efficient.
Code: (Demo)
$truthyCount = 0;
foreach ($array as $row) {
foreach ($row as $v) {
$truthyCount += (bool) $v;
}
}
var_export($truthyCount);
<?php
$mm = array
(
147 => array
(
"pts_m" => "",
"pts_mreg" => 1,
"pts_cg" => 1
) ,
158 => array
(
"pts_m" => null ,
"pts_mreg" => null,
"pts_cg" => 0
),
159 => array
(
"pts_m" => "",
"pts_mreg" => 1,
"pts_cg" => 1
)
);
$count = 0;
foreach ($mm as $m) {
foreach ($m as $value) {
if($value !== false && $value !== "" && $value !== null) {
$count++;
}
}
}
echo $count;
?>

Categories