muesli
muesli

Reputation: 106

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

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

Upvotes: 5

Views: 3345

Answers (3)

Barmar
Barmar

Reputation: 781848

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

Upvotes: 3

Don't Panic
Don't Panic

Reputation: 41820

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.

Upvotes: 4

Zak
Zak

Reputation: 7525

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
                                        (
                                        )

                                )

                        )

                )

        )

)

Upvotes: 1

Related Questions