Peretz
Peretz

Reputation: 15

equivalent of dict comprehensions in PHP

I'm looking for the equivalent in PHP of the following Python code:

d = {a*2:a*3 for a in range(5)}

Here's an ugly one-line solution:

$d = array_combine(array_map(function ($x) {return $x*2;}, range(0,4)), array_map(function ($x) {return $x*3;}, range(0,4)));

And here's a more readable solution that uses a loop :(

$d = [];
foreach(range(0,4) as $x) {
    $d[$x*2]  = $x*3;
}

Is there a simpler and better way to do this in PHP?

Upvotes: 1

Views: 1021

Answers (2)

Tgr
Tgr

Reputation: 28210

If the lazy evaluation of list comprehensions is what you are after, you can use a generator:

$d = iterator_to_array((function() {
    foreach(range(0,4) as $x) {
        yield $x*2 => $x*3;
    }
})());

Of course pretty pointless in this mock example where you immediately convert it to array, but something like

$gen = function($n) {
    for($x=0; $x<=$n; $x++) {
        yield $x*2 => $x*3;
    }
};
foreach($gen(1000000) as $k=>$v) {
    echo "$k => $v\n";
}

can iterate through a lot of values without having to load them all into memory beforehand.

Apparently there was a proposal to implement proper list comprehensions in PHP, but it has stalled.

Upvotes: 0

trincot
trincot

Reputation: 351074

There is no dictionary comprehension syntax in PHP. When looking for the shortest and/or most efficient code to produce the same output, I would propose this:

1. range(from, to, step)

You can make use of the third parameter of the range function:

$d = array_combine (range(0,8,2), range(0,12,3));

Output of var_export($d):

array (
  0 => 0,
  2 => 3,
  4 => 6,
  6 => 9,
  8 => 12,
)

Of course, this only works if your expressions are linear.

2. foreach

The foreach loop really is the cleanest and most readable way to handle this. Note that you have a little error in your version: the range function needs at least 2 arguments.

Also, PHP does not require you to initialise $d as it will do so upon the first assignment in the loop. Finally, you don't need the braces, although your preferred coding style may require the use of them:

foreach (range(0,4) as $x) $d[$x*2] = $x*3;

In number of characters this line is even shorter than the first solution.

Upvotes: 4

Related Questions