1

I am attempting to build a function that allows searching of multi-dimensional arrays where each sub-array matches multiple conditions. I'm encountering a weird behaviour and can't figure out why it is happening.

The following is the general logic that causes the issue. I'm running this on PHP 7.4 for what it's worth. The final array of keys ($keys2) is expected to match the first array of keys ($keys), but instead it loses its association with the expected indexes. It appears that PHP is ignoring my given int indexes and using un-seen 0-indexed indexes on the final array_keys() call instead.

$array = [
    ['one' => 'aa', 'two' => 'qq'],
    ['one' => 'bb', 'two' => 'qq'],
    ['one' => 'aa', 'two' => 'qq'],
    ['one' => 'bb', 'two' => 'qq'],
    ['one' => 'aa', 'two' => 'qq'],
];

$keys = array_keys(array_column($array, 'one'), 'aa');
$array2 = array_filter($array, static function($key) use ($keys) {
    return in_array($key, $keys, true);
}, ARRAY_FILTER_USE_KEY);
$keys2 = array_keys(array_column($array2, 'two'), 'qq');

echo '<pre>';
var_dump($array, $keys, $array2, $keys2);
echo '</pre>';

The above outputs:

/var/www/test.php:
array (size=5)
  0 => 
    array (size=2)
      'one' => string 'aa' (length=2)
      'two' => string 'qq' (length=2)
  1 => 
    array (size=2)
      'one' => string 'bb' (length=2)
      'two' => string 'qq' (length=2)
  2 => 
    array (size=2)
      'one' => string 'aa' (length=2)
      'two' => string 'qq' (length=2)
  3 => 
    array (size=2)
      'one' => string 'bb' (length=2)
      'two' => string 'qq' (length=2)
  4 => 
    array (size=2)
      'one' => string 'aa' (length=2)
      'two' => string 'qq' (length=2)
/var/www/test.php:
array (size=3)
  0 => int 0
  1 => int 2
  2 => int 4
/var/www/test.php:27:
array (size=3)
  0 => 
    array (size=2)
      'one' => string 'aa' (length=2)
      'two' => string 'qq' (length=2)
  2 => 
    array (size=2)
      'one' => string 'aa' (length=2)
      'two' => string 'qq' (length=2)
  4 => 
    array (size=2)
      'one' => string 'aa' (length=2)
      'two' => string 'qq' (length=2)
/var/www/test.php:
array (size=3)
  0 => int 0
  1 => int 1
  2 => int 2
4
  • 1
    array_column just returns the values from the column you specify; it doesn't look at the keys. Hence you get a result which is indexed as 0, 1, 2.... You might find this easier to implement via a simple foreach loop. Commented Apr 14, 2020 at 1:08
  • 1
    @Nick is correct, look at the output of array_column($array2, 'two'). You don't need to be a slave to the PHP array_x() functions, in instances like this it will look cleaner to write your own function. If you're looking for a quick solution, just use array_combine() with array_keys($array2) to apply the old keys to the new array. Commented Apr 14, 2020 at 1:30
  • The first call properly returns the expected keys. It appears from further testing that if you start with keys zero-indexed and consecutive you get the keys you want, but if you don't start at 0 or continue consecutively with the numeric keys, you don't. I tried it with string keys, and it seems to treat non-consecutive numeric keys as an associatively keyed array. Commented Apr 14, 2020 at 13:56
  • So I understand now that the first pass was working by coincidence, not by design. The existing 0-indexed keys lined up with my expected results. Working with array_combine() does the trick. Commented Apr 14, 2020 at 15:01

1 Answer 1

1
<?php 

$array = [
    ['one' => 'aa', 'two' => 'qq'],
    ['one' => 'bb', 'two' => 'qq'],
    ['one' => 'aa', 'two' => 'qq'],
    ['one' => 'bb', 'two' => 'qq'],
    ['one' => 'aa', 'two' => 'qq'],
];

$keys = array_keys(array_column($array, 'one'), 'aa');
$array2 = array_filter($array, static function($key) use ($keys) {
    return in_array($key, $keys, true);
}, ARRAY_FILTER_USE_KEY);

$keys2 = array_keys(array_combine(array_keys($array2), array_column($array2, 'two')), 'qq', true);

echo '<pre>';
var_dump($array, $keys, $array2, $keys2);
echo '</pre>';
Sign up to request clarification or add additional context in comments.

1 Comment

Thanks. It looks like maybe the first array_keys(array_column()) call threw me off and actually provided the unexpected behaviour, in that it preserved the keys making me think it should always. I'll probably have to use array_combine() on both lines to account for the potential of using associative indexes.

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.