Home > Back-end >  php stdClass Object manipulation - Laravel 8
php stdClass Object manipulation - Laravel 8

Time:06-08

I have an object as below,

{"metaData":[{"name":"a"},{"name":"b"}],"rows":[[1,2],[3,4],[5,6]]}

I would like to change it to

[["a"=>1,"b"=>2],["a"=>4,"b"=>5],["a"=>5,"b"=>6]]

Is there any faster one liner that can convert this without going thru a loop in Laravel ?

CodePudding user response:

You can get the keys with array_column, then map array_combine over the rows.

$keys = array_column($object->metaData, 'name');
$result = array_map(fn($row) => array_combine($keys, $row), $object->rows);

You could make it a one-liner like this, but it's more difficult to read, and it will call array_column for every row instead of just once.

$result = array_map(fn($row) => array_combine(array_column($object->metaData, 'name'), $row), $object->rows);

You need to be sure that each row is the same size as the metadata array or array_combine will fail. Based on the appearance of your object, it looks like this would probably always be true, but it's important to note.

CodePudding user response:

BUT. This is almost a one liner :)

$str = '{"metaData":[{"name":"a"},{"name":"b"}],"rows":[[1,2],[3,4],[5,6]]}';

$obj = json_decode($str);

$obj->rows = array_map( function ($a) {return ['a'=>$a[0], 'b'=>$a[1]];} , $obj->rows);
print_r($obj);
echo json_encode($obj);

RESULT

stdClass Object
(
    [metaData] => Array
        (
            [0] => stdClass Object
                ([name] => a)

            [1] => stdClass Object
                ([name] => b)
        )
    [rows] => Array
        (
            [0] => Array
                ([a] => 1,[b] => 2)

            [1] => Array
                ([a] => 3,[b] => 4)

            [2] => Array
                ( [a] => 5,[b] => 6)
        )
)

{"metaData":[{"name":"a"},{"name":"b"}],"rows":[{"a":1,"b":2},{"a":3,"b":4},{"a":5,"b":6}]}

UPDATE, Using the names form the metaData for the array indexes. Not a one liner any more, but it was fun rangling it

$str = '{"metaData":[{"name":"ali"},{"name":"bill"}],"rows":[[1,2],[3,4],[5,6]]}';

$obj = json_decode($str);

// get array of names
$names = array_map( function ($a) {return $a->name;}, $obj->metaData);

// use it in the array map to get any number of names
$rows = array_map( function ($a) use($names) {
                        for( $x=0; $x<count($names); $x  ) {
                            $ret[] = [$names[$x]=>$a[$x]];
                        }
                        return $ret;
                    }
                , $obj->rows);

$obj->rows = $rows;
print_r($obj);
echo json_encode($obj);

NEW RESULTS

stdClass Object
(
    [metaData] => Array
        (
            [0] => stdClass Object
                (
                    [name] => ali
                )

            [1] => stdClass Object
                (
                    [name] => bill
                )

        )

    [rows] => Array
        (
            [0] => Array
                (
                    [0] => Array
                        (
                            [ali] => 1
                        )

                    [1] => Array
                        (
                            [bill] => 2
                        )

                )

            [1] => Array
                (
                    [0] => Array
                        (
                            [ali] => 3
                        )

                    [1] => Array
                        (
                            [bill] => 4
                        )

                )

            [2] => Array
                (
                    [0] => Array
                        (
                            [ali] => 5
                        )

                    [1] => Array
                        (
                            [bill] => 6
                        )

                )

        )

)
{"metaData":[{"name":"ali"},{"name":"bill"}],"rows":[[{"ali":1},{"bill":2}],[{"ali":3},{"bill":4}],[{"ali":5},{"bill":6}]]}
  • Related