1

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!

2
  • Does Needle has constant key name? Commented Jan 8, 2017 at 16:20
  • Sorry, yes it does "child_answers" to be precise Commented Jan 8, 2017 at 16:21

3 Answers 3

2

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
Sign up to request clarification or add additional context in comments.

3 Comments

Would it not be easier to recursively call the function? passing the processed data as a secondary attribute?
@DarylGill: Quite right! Even though I did some sorting in my code it will most likely not work reliably with deeper "needle" arrays. This was just a "quick shot" done on the basis of shalvahs's post. A recursive code is very likely the better approach. Maybe, you can put together a little example ;-) ...
@cars10 looping over the needle array? Isn't $nearr 1D while $haystack 2D?
1

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

Comments

1

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;
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.