Lex Hartman
Lex Hartman

Reputation: 178

check if array is in two multidimensional array

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

Answers (3)

shalvah
shalvah

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

AbraCadaver
AbraCadaver

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

Carsten Massmann
Carsten Massmann

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

Related Questions