'Distribute array row data to make multiple new rows

I have below the data

[
    {
        "price_in_dollar": 1000,
        "price_in_euro": 1000,
        "price_in_pound": 1000,
        "price_in_rupee": 1000,
        "toy_id": 1,
        "toy_name": "Truck"
    },
    {
        "price_in_dollar": 1000,
        "price_in_euro": 1000,
        "price_in_pound": 1000,
        "price_in_rupee": 1000,
        "toy_id": 2,
        "toy_name": "Bicycle"
    }
]

I want to create a new array from above as below

[
    {
        "toy": "Truck",
        "toy_id": 1,
        "rate": 1000,
        "slug": "price_in_dollar",
    },
    {
        "toy": "Truck",
        "toy_id": 1,
        "rate": 1000,
        "slug": "price_in_euro",
    },
    ...
    {
        "toy": "Bicycle",
        "toy_id": 2,
        "rate": 1000,
        "slug": "price_in_dollar",
    },
    {
        "toy": "Bicycle",
        "toy_id": 2,
        "rate": 1000,
        "slug": "price_in_euro",
    },
    ...

]

I have tried the below code

foreach($data as $r) {
    foreach($r as $key => $value) {

        if ($key === 'toy_name') {
            $cars['toy'] =  $value ;
        }
        else if ($key === 'toy_id') {
            $cars['toy_id'] =  $value;
        }
        else {
            $cars['slug'] =  $key ;
            $cars['rate'] =  $value;
        }
    }
}

But it only has one set of data, how can I append all data? Or any improved code to solve this?



Solution 1:[1]

your code was actually replacing a key => value pair data, not pushing a data into $cars, you can fix it like this:

$cars = [];
foreach($data as $r) {
    $singleCar = [
        "toy_id" => $r['toy_id'],
        "toy" => $r['toy_name'],
    ];
    
    foreach($r as $key => $val){
        if($key != 'toy_id' && $key != 'toy_name') {
            $singleCar['rate'] = $val;
            $singleCar['slug'] = $key;
            
            $cars[] = $singleCar;
        }
    }
}

Solution 2:[2]

Something like the below is working fine:

$data= [
    [
        "price_in_dollar" => 1000,
        "price_in_euro" => 1000,
        "price_in_pound" => 1000,
        "price_in_rupee" => 1000,
        "toy_id" => 1,
        "toy_name" => "Truck"
    ],
    [
        "price_in_dollar" => 1000,
        "price_in_euro" => 1000,
        "price_in_pound" => 1000,
        "price_in_rupee" => 1000,
        "toy_id" => 2,
        "toy_name" => "Bicycle"
    ]
];

$cnt = 0;

foreach($data as $r) {
    foreach($r as $key => $value) {

        if ($key === 'toy_name') {
            $cars[$cnt]['toy'] =  $value ;
        }
        else if ($key === 'toy_id') {
            $cars[$cnt]['toy_id'] =  $value;
        }
        else {
            $cars[$cnt]['slug'] =  $key ;
            $cars[$cnt]['rate'] =  $value;
        }
    }
    
    $cnt++;
}

// display result
print_r($cars);

Solution 3:[3]

try like

foreach($data as $r) {
foreach($r as $key => $value) {

    if ($key === 'toy_name') {
        $cars[]['toy'] =  $value ;
    }
    else if ($key === 'toy_id') {
        $cars[]['toy_id'] =  $value;
    }
    else {
        $cars[]['slug'] =  $key ;
        $cars[]['rate'] =  $value;
    }
}

}

Solution 4:[4]

I would loop for the different currencies and use some php array functions

$currencies = ['price_in_dollar', 'price_in_euro', 'price_in_pound', 'price_in_rupee'];

$data= [
    ...
];
$newData = [];
foreach($currencies as $currency) {
    $newData = array_merge(
        $newData, 
        array_map(function ($item) use ($currency) {
            return [
                "toy" => $item['toy_name'],
                "toy_id" => $item['toy_id'],
                "rate" => $item[$currency],
                "slug" => $currency,
            ];
        }, $data)
    );
}

Solution 5:[5]

As you iterate each row, isolate the repeatable elements, then removed them from the row, then iterate the remaining elements and push the new desired associative rows into the result array.

The unset() call will not actually affect the original input array because the forearch is actually iterating a "copy" of the input array.

Code: (Demo)

$result = [];
foreach ($data as $row) {
    ['toy_id' => $id, 'toy_name' => $name] = $row;
    unset($row['toy_id'], $row['toy_name']);
    foreach ($row as $slug => $rate) {
        $result[] = compact(['id', 'name', 'slug', 'rate']);
    }
}
var_export($result);

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1
Solution 2 Mouhamad Ounayssi
Solution 3 Usman Ali
Solution 4 John Zwarthoed
Solution 5 mickmackusa