0

Given the following haystack and needle:

$haystack = array(
  'foo' => array(
    1 => 'one',
    2 => 'two',
    3 => 'three',
  ),
);

$needle = array(
  'foo' => array(
    1 => 'one',
    2 => 'two',
  ),
);

I want to check if all nested key-value pairs of the needle occur in the haystack (like it does in the example above), while ignoring any additional key-value pairs that may exist in the haystack (like $haystack['foo'][3] in the example).

There are many similar questions on SO but I haven't found a solution for this specific use case. Is there a (combination of) standard PHP functions to do this? What is the most elegant solution?

[update]

I didn't make clear yet that the arrays may not always have the same depth. Also, the keys of the elements in the arrays may be different every time.

5
  • 1
    You should show what you've tried. I have an answer posted but deleted as I prefer to answer questions that show effort. Commented Mar 6, 2015 at 16:03
  • So, you want to check if $needle is inside $haystack ?? Commented Mar 6, 2015 at 16:03
  • @JohnConde I know, I'll post what I came up with as an answer. Commented Mar 6, 2015 at 16:07
  • @sam_io yes, that is what I want to know, taking all nested levels of both arrays into account. Commented Mar 6, 2015 at 16:08
  • @marcvangend I tried :/ sadly it's too tricky, and me got no time. It is quite interesting challenge. good luck :) +1 for the question. Commented Mar 6, 2015 at 16:59

2 Answers 2

2

array_intersect() will tell you what values match. Just make sure that matches your $needle.

echo $needle['foo'] === array_intersect($needle['foo'], $haystack['foo']);
Sign up to request clarification or add additional context in comments.

5 Comments

If I'm not mistaken, this will only work with arrays that are one level deep, right?
If I change the values I still get a match.
So, what if the haystack and needle not always have the same depth? And what if the foo element is not always called foo?
If it is a nested array than this won't work and there is no "elegant" way to do this. The array key can obviously be dynamic in your code.
I think this is doable as the OP requested, but not without less than at-least 10 lines of code. However, this answer does not enable dynamic keys, or more depth.
0

This is what I came up with myself. It works, but it seems more complex than it should be...

/**
 * Helper function which recursively checks if the key-value pairs in one array
 * are all present in another array. If all key-value pairs in the needle are
 * present in the haystack, and the haystack also contains additional items,
 * the check wil still pass.
 *
 * @param array $needle
 *   The array with the key-value pairs to look for.
 * @param array $haystack
 *   The array in which to look for the key-value pairs.
 * @return bool
 *   TRUE if all key-value pairs of the needle occur in the haystack. FALSE if
 *   one or more keys or values are missing or different.
 */
function array_contains(array $needle, array $haystack) {
  // First, check if needle and haystack are identical. In that case it's easy.
  if ($needle === $haystack) {
    return TRUE;
  }
  foreach ($needle as $key => $value) {
    // If the key does not occur in the haystack, we're done.
    if (!isset($haystack[$key])) {
      return FALSE;
    }
    // If the value is an array...
    if (is_array($value)) {
      // ...see if the counterpart in $haystack is an array too...
      if (!is_array($haystack[$key])) {
        return FALSE;
      }
      // ...and if so, recurse.
      if (array_contains($value, $haystack[$key]) == FALSE) {
        return FALSE;
      }
    }
    // If the values are not arrays and not the same, the check fails.
    else if ($value != $haystack[$key]) {
      return FALSE;
    }
  }
  // If we still didn't fail, all tests have passed.
  return TRUE;
}

2 Comments

Modify your OP to add this.
@JayBlanchard I have been criticized by mods before for including a possible answer in my question, telling me that is should be an answer instead...

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.