Reputation: 178
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!
Upvotes: 1
Views: 119
Reputation: 895
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;
}
Upvotes: 1
Reputation: 78984
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
Upvotes: 1
Reputation: 28206
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
Upvotes: 2