20

I have an array with 2 kinds of keys, strings and integers. I want to do foreach() on this array and want to do it for numeric keys only. What is the most elegant way of doing it?

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
henrijs
  • 1,010
  • 2
  • 11
  • 19

4 Answers4

30

Here's a complicated method using array_filter() to return the numeric keys then iterate over them.

// $input_array is your original array with numeric and string keys
// array_filter() returns an array of the numeric keys
// Use an anonymous function if logic beyond a simple built-in filtering function is needed
$numerickeys = array_filter(array_keys($input_array), function($k) {return is_int($k);});

// But in this simple case where the filter function is a plain
// built-in function requiring one argument, it can be passed as a string:
// Really, this is all that's needed:
$numerickeys = array_filter(array_keys($input_array), 'is_int');

foreach ($numerickeys as $key) {
  // do something with $input_array[$key']
}

It's much easier though to just foreach over everything:

foreach ($input_array as $key => $val) {
  if (is_int($key)) {
    // do stuff
  }
}

Edit Misread original post and thought I saw "numeric" rather than "integer" keys. Updated to use is_int() rather than is_numeric().

Michael Berkowski
  • 267,341
  • 46
  • 444
  • 390
  • 2
    The anonymous function in `array_filter` could be replaced by the string `'is_int'` :) – Ja͢ck Apr 09 '13 at 06:59
  • @Jack Thank's for digging up an ancient answer. Answer expanded. – Michael Berkowski Apr 09 '13 at 10:57
  • But how efficient do you think think this might be? Many times worse than `foreach(*){if(is_int)(do stuff;)}` Or about the same? Based on the function's description, I would have to say this is at least 2 times more processor intensive, and that is not even taking into account the creation of a whole new variable. – Jonathon May 02 '13 at 18:15
  • @JonathonWisnoski Whenever efficiency is a real concern, setup a benchmark to test it. Anonymous functions as in the first sample are generally slower than `foreach` loops, often by a lot. The second may be a bit faster than the first, calling bare `is_int()` as a callback. – Michael Berkowski May 02 '13 at 18:21
11
    foreach($array as $key => $val) {
        if(!is_int($key))
             continue;
        // rest of the logic
    }
Ehtesham
  • 2,967
  • 1
  • 18
  • 20
  • yeah its different but OP said integers. – Ehtesham Oct 30 '11 at 21:37
  • True, they do (and it's possible that `int` is what they meant in practice). However, `numeric` is used several times, including the question title. – Jared Farrish Oct 30 '11 at 21:39
  • 2
    Actually, it doesn't matter. [PHP always stores numeric keys as ints.](http://stackoverflow.com/questions/4100488/a-numeric-string-as-array-key-in-php/4100765#4100765) –  Oct 30 '11 at 21:40
6

This one-liner returns a new array with the values and its numeric keys:

$new_array = array_filter($my_array, 'is_int', ARRAY_FILTER_USE_KEY);

so if we have this:

array(
'fruit' => 'banana'
1 => 'papaya'
)

..we get this:

array(
1 => 'papaya'
)
Ignacio Segura
  • 678
  • 8
  • 15
1

Using array_filter you must aware if you have value that similar as FALSE.

This is my solution:

function filterArrayKeyInteger(Array $array) {
    $integer = array_filter($array, function ($key) {
        if ($key === 0 || is_int($key)) {
            return true;
        }
    }, ARRAY_FILTER_USE_KEY);
    return array_intersect_key($array, $integer);
}

$a = [0, false, 'aa','bb', 'cc', 'dd' => 'dd', '9.9' => 9.9];    
$b = filterArrayKeyInteger($a);

Result of vardump

var_dump(a): array(7) {
  [0]=>
  int(0)
  [1]=>
  bool(false)
  [2]=>
  string(2) "aa"
  [3]=>
  string(2) "bb"
  [4]=>
  string(2) "cc"
  ["dd"]=>
  string(2) "dd"
  ["9.9"]=>
  float(9.9)
}

var_dump(b): array(5) {
  [0]=>
  int(0)
  [1]=>
  bool(false)
  [2]=>
  string(2) "aa"
  [3]=>
  string(2) "bb"
  [4]=>
  string(2) "cc"
}
IjorTengab
  • 41
  • 2