18

Is there a cleaner way than foreach to get an array of all "label" values?

$methods[0]['label'] = 'test';
$methods[0]['nr']    = 99;
$methods[1]['label'] = 'whatever';
$methods[1]['nr']    = 10;


foreach($methods as $method) {
    $methodsLabel[] = $method['label'];
}
powtac
  • 40,542
  • 28
  • 115
  • 170
  • I do not think foreach is unclean. Do you think it is unclean because you prefer functional programming? – Geoffrey Feb 24 '11 at 17:56
  • 3
    I also think your code is just fine the way it is. Not only will it be fast, but also very easy to read and maintain... everyone knows how to look at a foreach! – Petar Zivkovic May 22 '13 at 10:02

7 Answers7

29

No, there is no faster way than your implemented code. All other methods will be slower due to the overhead of a function call. For a small array the difference will be trivial, but for a large one (100 members or so, depending on implementation), the difference can be huge...

You could array_map it, but I'd stick with the raw PHP you posted above... It's easier to maintain and IMHO more readable...

After all, tell me which at a glance tells you what it does more:

$results = array();
foreach ($array as $value) {
    $results[] = $value['title'];
}

vs

$results = array_map(function($element) {
        return $element['title'];
    },
    $array
);

Or:

$callback = function($element) {
    return $element['title'];
}
$results = array_map($callback, $array);

Personally, the first does it for me the best. It's immediately obvious without knowing anything what it's doing. The others require knowledge of array_map semantics to understand. Couple that with the fact that array_map is slower, and it's a double win for foreach.

Code should only be as elegant as necessary. It should be readable above all else...

ircmaxell
  • 163,128
  • 34
  • 264
  • 314
  • 1
    I changed my description, I was not searching for a fast solution I was searching for a more cleaner solution. – powtac Feb 24 '11 at 17:41
  • 2
    @powtac: I still stand behind a straight foreach is more readable and easier to understand. And you're talking the same if not less code with the foreach, so I fail to see the benefit... – ircmaxell Feb 24 '11 at 17:42
18

Sure, use array_map:

function getLabelFromMethod($method) {
   return $method['label'];
}

$labels = array_map('getLabelFromMethod', $methods);

If you are on PHP 5.3+, you can also use a lambda function:

$labels = array_map(function($m) {
   return $m['label'];
}, $methods);
Jacob Relkin
  • 161,348
  • 33
  • 346
  • 320
10

As of PHP 5.5+, this is exactly what array_column() does:

$methodsLabel = array_column($methods, 'label');

http://php.net/manual/function.array-column.php


3v4l example: https://3v4l.org/ZabAb

powtac
  • 40,542
  • 28
  • 115
  • 170
autonymous
  • 303
  • 3
  • 4
  • This is an interesting find as my Sublime Text doesn't know of that function and, therefore, doesn't provide auto completion for this. – sjngm Feb 04 '19 at 14:00
6
array_map('array_shift', $methods);

Here assumption is that label will be the first element of each array.

Gaurav
  • 28,447
  • 8
  • 50
  • 80
5

On PHP 5.3+ you can use an anonymous function paired with array_map.

$methodsLabel = array_map(function($item) { return $item['label']; }, $methods);
efritz
  • 5,125
  • 4
  • 24
  • 33
3

If label is first element in array then "current" with array_map will work fine.

array_map('current', $methods); 
Ravi Hirani
  • 6,511
  • 1
  • 27
  • 42
2

Arrow functions have been introduced into PHP 7.4, which makes this a little bit cleaner.

$methodsLabel = array_map(fn($x) => $x['label'], $methods)
Gary Thomas
  • 2,291
  • 1
  • 9
  • 21