9

I'm trying to exclude foreach-loops and refactor them with array functions. I was under the assumption the code below would give me a result with all first items from the source array.

<?php
    $data= [
        0 => [1, 'test1'],
        1 => [2, 'test2'],
        2 => [3, 'test3'],
    ];

    $ids = array_filter($data, function($item) {
        return $item[0];
    });

    var_dump($ids);

But when I var_dump $ids I get the output:

array (size=3)
  0 => 
    array (size=2)
      0 => int 1
      1 => string 'test1' (length=5)
  1 => 
    array (size=2)
      0 => int 2
      1 => string 'test2' (length=5)
  2 => 
    array (size=2)
      0 => int 3
      1 => string 'test3' (length=5)

Why isn't the output:

array (size=3)
  0 => int 1
  1 => int 2
  2 => int 3
Ben Fransen
  • 10,884
  • 18
  • 76
  • 129
  • 1
    The array_filter() callback returns a true/false indicating whether the element should be included or excluded from the filtered array; you're always returning a truthy value – Mark Baker May 18 '16 at 12:25
  • 2
    If you want to get just the ids (column `0`), then you should be using [array_column()](http://www.php.net/manual/en/function.array-column.php): `$ids == array_column($data, 0);` – Mark Baker May 18 '16 at 12:27
  • `array_column` works like a charm! And I believe it's exactly what I need in this case. – Ben Fransen May 18 '16 at 12:28
  • [array_filter() is not working as intended](https://stackoverflow.com/q/26824960/2943403) and [Manipulate array filter in php value array not change](https://stackoverflow.com/q/73903968/2943403) and [Why doesn't array_filter() mutate my strings while it iterates?](https://stackoverflow.com/q/51291802/2943403) and [problem in array_filter() and strlen function](https://stackoverflow.com/q/63754338/2943403) – mickmackusa Dec 11 '22 at 12:32

5 Answers5

17

array_filter is used for filtering out elements of an array based on whether they satisfy a certain criterion. So you create a function that returns true or false, and test each element of the array against it. Your function will always return true, since every array has a first element in it, so the array is unchanged.

What you're looking for is array_map, which operates on each element in an array by running the callback over it.

<?php
$data= [
    0 => [1, 'test1'],
    1 => [2, 'test2'],
    2 => [3, 'test3'],
];

$ids = array_map(function($item) {
    return $item[0];
}, $data);

var_dump($ids);

As another answer mentions, if all you want to do is extract a single "column", then array_column is a much simpler option.

iainn
  • 16,826
  • 9
  • 33
  • 40
10

Try this code

$data= [
        0 => [1, 'test1'],
        1 => [2, 'test2'],
        2 => [3, 'test3'],
    ];

    $ids = array_column($data, 0);
    var_dump($ids);
  • 3
    This is the best answer, it's a shame that it is a code-only answer from a deleted user. This is exactly what `array_column()` is for. – mickmackusa Oct 13 '18 at 16:23
2

The filter function needs to return a boolean(or any value that can be coerced to true) for each item so that it can be spared. So in your case it is always returning true for every element in the array

To get the result you 'd have to array_walk;

 $data = [
        0 => [1, 'test1'],
        1 => [2, 'test2'],
        2 => [3, 'test3'],
     ];


 array_walk($data, function($value, $key) use ($data){
                  $data[$key] = $value[0];
           })
Peter Chaula
  • 3,456
  • 2
  • 28
  • 32
  • That looks more complicated than the suggested `array_column` or `array_map`. Thanks for the contribution to show `array_walk`'s possibilities. +1 – Ben Fransen May 18 '16 at 12:38
0

the function included in the array_filter must return either true or false. 0 or empty array are converted to FALSE. Non-zero numbers are considered as true.

so if you want to find an item with id 2, you should compare it with 2 like this

<?php
$data= [
    0 => [1, 'test1'],
    1 => [2, 'test2'],
    2 => [3, 'test3'],
];

$ids = array_filter($data, function($item) {
    return $item[0] == 2;
});

var_dump($ids);

output

array(1) {
  [1] =>
  array(2) {
    [0] =>
    int(2)
    [1] =>
    string(5) "test2"
  }
}
Richard
  • 1,045
  • 7
  • 11
0

Try below code

$data= [
        0 => [1, 'test1'],
        1 => [2, 'test2'],
        2 => [3, 'test3'],
    ];

    $ids = array_map(function($item) {
        return $item[0];
    }, $data);

    var_dump($ids);
Jignesh Patel
  • 1,028
  • 6
  • 10