Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the PHP equivalent of JavaScript spread syntax for constructing an array?

Tags:

javascript

php

Asked already a question about converting functions from Ruby to JS, and now I'm trying to implement with JS to PHP, but something does not work, tell me what I'm missing?

The code on JS:

function transpose(a) {
    return a.length === 0 ? a : a[0].map((col, i) => a.map((row) => row[i]))
}

function f(a) {
    return a.length === 0 ? [] : [...a.shift(), ...f(transpose(a).reverse())];
} 

console.log(f([[1, 2, 3, 4], [12, 13, 14, 5], [11, 16, 15, 6], [10, 9, 8, 7]]))

In PHP do so:

function transpose($array) 
{
    if (count($array) === 0) return $array;

    foreach ($array as  $rowkey => $row)
    {
        foreach($row as $colkey => $col)
        {
            $out[$colkey][$rowkey] = $col;
        }
    }

    return $out;
}

function f($a)
{
    return (count($a) === 0) 
    ? [] 
    : [
        array_shift(...$a), 
        f(array_reverse(transpose(...$a)))
    ];
}

print_r(f([[1,2,3,4],[10,11,12,5],[9,8,7,6]]));

Is there a problem? Errors:

Warning: array_shift() expects exactly 1 parameter, 3 given in [...][...] on line 24

Invalid argument supplied for foreach() in [...][...] on line 10

Warning: Invalid argument supplied for foreach() in [...][...] on line 10

Warning: Invalid argument supplied for foreach() in [...][...] on line 10

Warning: Invalid argument supplied for foreach() in [...][...] on line 10

Notice: Undefined variable: out in [...][...] on line 16

Warning: array_reverse() expects parameter 1 to be array, null given in [...][...] on line 25 Warning: count(): Parameter must be an array or an object that implements Countable in [...][...] on line 21

like image 401
muesli Avatar asked Oct 22 '18 21:10

muesli


3 Answers

You don't need to use the ... operator in the PHP version. You just need to merge the shifted row with the result of the recursive call.

function f($a)
{
    return (count($a) === 0) 
    ? [] 
    : array_merge(
        array_shift($a), 
        f(array_reverse(transpose($a)))
    );
}

array_merge(array_shift($a), f(array_reverse(transpose($a))))

is the same thing that's happening here:

[...a.shift(), ...f(transpose(a).reverse())]

... expands the elements of the array in JS. It works similarly in PHP, but here it is only valid in function definitions or calls.

like image 169
Don't Panic Avatar answered Oct 17 '22 05:10

Don't Panic


You have your ... (AKA "splat") operators in a different place in the PHP than the JS.

Also, prior to PHP 7.4 the splat operator can't be used in array literals, only in function calls. The use in the f() function is equivalent to array_merge().

function f($a)
{
    return (count($a) === 0) 
    ? [] 
    : array_merge(
        array_shift($a), 
        f(array_reverse(transpose($a)))
    );
}

DEMO

like image 45
Barmar Avatar answered Oct 17 '22 07:10

Barmar


Your array_shift has too many parameters .. All you need is the $a Same with array_reverse

<?php
function transpose($array)
{
    if (count($array) === 0) return $array;

    foreach ($array as  $rowkey => $row)
    {
        foreach($row as $colkey => $col)
        {
            $out[$colkey][$rowkey] = $col;
        }
    }

    return $out;
}

function f($a)
{
    return (count($a) === 0)
    ? []
    : [
        array_shift($a),
        f(array_reverse(transpose($a)))
    ];
}

print_r(f([[1,2,3,4],[10,11,12,5],[9,8,7,6]]));

RESULT

Array
(
    [0] => Array
        (
            [0] => 1
            [1] => 2
            [2] => 3
            [3] => 4
        )

    [1] => Array
        (
            [0] => Array
                (
                    [0] => 5
                    [1] => 6
                )

            [1] => Array
                (
                    [0] => Array
                        (
                            [0] => 7
                            [1] => 8
                            [2] => 9
                        )

                    [1] => Array
                        (
                            [0] => Array
                                (
                                    [0] => 10
                                )

                            [1] => Array
                                (
                                    [0] => Array
                                        (
                                            [0] => 11
                                            [1] => 12
                                        )

                                    [1] => Array
                                        (
                                        )

                                )

                        )

                )

        )

)
like image 1
Zak Avatar answered Oct 17 '22 05:10

Zak