19

I have an array that looks something like this:

Array
(
    [0] => apple
    ["b"] => banana
    [3] => cow
    ["wrench"] => duck
)

I want to take that array and use array_filter or something similar to remove elements with non-numeric keys and receive the follwoing array:

Array
(
    [0] => apple
    [3] => cow
)

I was thinking about this, and I could not think of a way to do this because array_filter does not provide my function with the key, and array_walk cannot modify array structure (talked about in the PHP manual).

kjones
  • 1,339
  • 1
  • 13
  • 28
diracdeltafunk
  • 1,178
  • 2
  • 10
  • 24

4 Answers4

37

Using a foreach loop would be appropriate in this case:

foreach ($arr as $key => $value) {
    if (!is_int($key)) {
        unset($arr[$key]);
    }
}
  • PHP newbie here. I had a 2D array, and I used this to update my inner loop. I could tell from print statements that the inner loop was being updated, but for some reason the entire 2D array stayed the same. I had to add another line at the end. So if the outer loop was `foreach ($everything as $index => $arr)`, you need `$everything[$index] = $arr;`. – Bartleby Apr 25 '20 at 06:21
25

It can be done without writing a loop in one (long) line:

$a = array_intersect_key($a, array_flip(array_filter(array_keys($a), 'is_numeric')));

What it does:

  • Since array_filter works with values, array_keys first creates a new array with the keys as values (ignoring the original values).
  • These are then filtered by the is_numeric function.
  • The result is then flipped back so the keys are keys once again.
  • Finally, array_intersect_key only takes the items from the original array having a key in the result of the above (the numeric keys).

Don't ask me about performance though.

smhg
  • 2,159
  • 19
  • 26
  • How can i check the array key not numeric. I am trying with is_string function in array_filter callback but getting an error – karim_fci Aug 29 '15 at 10:13
  • What error are you getting? As you can see here, this seems to work: https://3v4l.org/aj9FD – smhg Aug 29 '15 at 13:24
  • 2
    for sake of truth, `array_filter` actually is a loop. You are not "writing" a loop, but internally it is. – kekko12 Mar 10 '16 at 10:54
  • If you choose to use this answer, keep in mind that despite of `array_intersect_key` with `is_numeric` filter, you can simply use `is_string` filter. – JoDev Feb 19 '18 at 09:43
23

As of PHP 5.6, it's now possible to use array_filter in a compact form:

array_filter($array, function ($k) { return is_numeric($k); }, ARRAY_FILTER_USE_KEY);

Demo.

This approach is about 20% slower than a for loop on my box (1.61s vs. 1.31s for 1M iterations).


As of PHP 7.4, it's possible to also use short closures::

array_filter($array, fn($k) => is_numeric($k), ARRAY_FILTER_USE_KEY);
bishop
  • 37,830
  • 11
  • 104
  • 139
  • 16
    You can also just pass the function name as a string. I.e. `array_filter($array, "is_numeric", ARRAY_FILTER_USE_KEY);` – Sean Oct 19 '16 at 23:56
7

Here's a loop:

foreach($arr as $key => $value) {
    if($key !== 0 and !intval($key)) {
         unset($arr[$key]);
    }
}
Scott Saunders
  • 29,840
  • 14
  • 57
  • 64