87

Python has syntactically sweet list comprehensions:

S = [x**2 for x in range(10)]
print S;
[0, 1, 4, 9, 16, 25, 36, 49, 64, 81]

In PHP I would need to do some looping:

$output = array();
$Nums = range(0,9);

foreach ($Nums as $num) 
{
    $out[] = $num*=$num;
}
print_r($out);

to get:

Array ( [0] => 0 [1] => 1 [2] => 4 [3] => 9 [4] => 16 [5] => 25 [6] => 36 [7] => 49 [8] => 64 [9] => 81 )

Is there anyway to get a similar list comprehension syntax in PHP? Is there anyway to do it with any of the new features in PHP 5.3?

Thanks!

dreftymac
  • 31,404
  • 26
  • 119
  • 182
Darren Newton
  • 2,847
  • 1
  • 29
  • 31
  • 1
    I'd say an even better example of how awesome python list comprehensions are is the conditionals! x = [x*2 for x in range(1,9) if x < 3] or whatever Bet that can't be done with array map! – Jonathan Feb 26 '15 at 00:09
  • 1
    **See also:** passing variables into anonymous function https://stackoverflow.com/questions/11420520/php-variables-in-anonymous-functions – dreftymac Jul 27 '18 at 21:27

4 Answers4

103

Maybe something like this?

$out=array_map(function($x) {return $x*$x;}, range(0, 9))

This will work in PHP 5.3+, in an older version you'd have to define the callback for array_map separately

function sq($x) {return $x*$x;}
$out=array_map('sq', range(0, 9));
Paul Dixon
  • 295,876
  • 54
  • 310
  • 348
  • 1
    Nice answer. +1. Not exactly list comprehension, but it's a very elegant and short solution nevertheless. Have a care tho, this is PHP 5.3+ since an anonymous function is used. – Lior Cohen Aug 12 '09 at 15:33
  • 4
    PHP 5.3 required. But nice solution :) – Sebastian Hoitz Aug 12 '09 at 15:34
  • create_function() could probably be used with PHP < 5.3 – Lior Cohen Aug 12 '09 at 15:36
  • you could use create_function, but it looks bloody ugly - far clearer just to define a new function IMHO! – Paul Dixon Aug 12 '09 at 15:38
  • Wow, very elegant! Another reason to upgrade to 5.3. Thanks! – Darren Newton Aug 12 '09 at 16:02
  • 1
    For comprehensions are a convenience over map, reduce and filter operations. For that matter between array_map, array_reduce, and array_filter you could have everything, a thin library using the __invoke() magic method and you could get a full on _pretty_ functional API. – Saem Aug 12 '09 at 18:56
  • 1
    Can you use this with A constructor? `array_map("new MyClass", range(0,9))`? – Thomas Ahle Apr 13 '11 at 10:06
  • 1
    Actually this is not list comprehension. (Python has `map` function too.) Though `map` and list comprehension are similar. – weakish Dec 06 '13 at 13:42
  • this is not the same thing. take, for instance, this list comprehension: [x for x in collection if x.meetsCondition()] – LRMAAX Jun 03 '17 at 20:59
6

PHP 5.5 may support list comprehensions - see the mailing list announcement:

And further discussion:

hakre
  • 193,403
  • 52
  • 435
  • 836
David Goodwin
  • 4,184
  • 1
  • 22
  • 12
2

not out of the box, but take a look at: http://code.google.com/p/php-lc/ or http://code.google.com/p/phparrayplus/

Rufinus
  • 29,200
  • 6
  • 68
  • 84
-2

In .NET, the equivalent of Python's "syntactically sweet list comprehensions" is LINQ. And in PHP, there're several ports of it, including YaLinqo library*. Syntactically, it's closer to SQL rather than a sequence of traditional constructs with for and if, but functionally, it's similar:

$a = Enumerable::range(0, 10)->select('$v * $v');

This produces an iterator which can either be output to console:

var_dump($a->toArray()); // by transforming the iterator to an array
echo $a->toString(', '); // or by imploding into a string

or iterated over using foreach:

foreach ($a as $i)
    echo $i, PHP_EOL;

Here, '$v * $v' is a shortcut for function ($v) { return $v * $v; } which this library supports. Unfortunately, PHP doesn't support short syntax for closures, but such "string lambdas" can be used to make the code shorter.

There're many more methods, starting with where (if equivalent) and ending with groupJoin which performs joining transformation with grouping.

* developed by me

Athari
  • 33,702
  • 16
  • 105
  • 146