Search code examples
phparraysmultidimensional-arraygroupinghierarchical-data

Convert 2d array into 3d associative array using a column value for first level and another column for second level


My array (stored in $r) currently looks like this... (3 entries with the same date in this example per day, sometimes there are more that share the same date.)

Array
(
    [0] => Array
        (
            [id] => 1
            [date_inserted] => 2020-09-06
            [marketplace] => Etsy
            [total_stickers] => 11
            [total_orders] => 8
            [total_value] => 41.62

    [1] => Array
        (
            [id] => 2
            [date_inserted] => 2020-09-06
            [marketplace] => Woo
            [total_stickers] => 2
            [total_orders] => 1
            [total_value] => 7.98
        )

    [2] => Array
        (
            [id] => 3
            [date_inserted] => 2020-09-06
            [marketplace] => eBay
            [total_stickers] => 44
            [total_orders] => 40
            [total_value] => 115.63
        )

    [3] => Array
        (
            [id] => 4
            [date_inserted] => 2020-09-07
            [marketplace] => Etsy
            [total_stickers] => 8
            [total_orders] => 4
            [total_value] => 34.92
        )

    [4] => Array
        (
            [id] => 5
            [date_inserted] => 2020-09-07
            [marketplace] => Woo
            [total_stickers] => 9
            [total_orders] => 3
            [total_value] => 52.90
        )

    [5] => Array
        (
            [id] => 6
            [date_inserted] => 2020-09-07
            [marketplace] => eBay
            [total_stickers] => 23
            [total_orders] => 21
            [total_value] => 58.03
        )

    )

I feel this would be better if the dates were the keys and the details for each date were combined, also [id] is not needed and the "marketplace" may as well be the key for the inner arrays thus my final output I would like is like this..

Array
(
    [2020-09-06] => Array (
       
            [Etsy] => Array
                (
                    [total_stickers] => 11
                    [total_orders] => 8
                    [total_value] => 41.62
                )
   
            [Woo] => Array
                (
                    [total_stickers] => 2
                    [total_orders] => 1
                    [total_value] => 7.98
                )

    
            [eBay] => Array
                (
                    [total_stickers] => 44
                    [total_orders] => 40
                    [total_value] => 115.63
                )
                        )
                        
    [2020-09-07] => Array (
       
            [Etsy] => Array
                (
                    [total_stickers] => 8
                    [total_orders] => 4
                    [total_value] => 34.92
                )
   
            [Woo] => Array
                (
                    [total_stickers] => 9
                    [total_orders] => 3
                    [total_value] => 52.90
                )

    
            [eBay] => Array
                (
                    [total_stickers] => 23
                    [total_orders] => 21
                    [total_value] => 58.03
                )
                        )                   
)

I've been looking at array_merge_recursive, also array_combine and also similar questions on here but can't seem to work out how to go about getting the results i want.

This is what I've tried (based on an answer from Lawrence Cherone)

$results = [];
foreach (array_column($r, 'date_inserted') as $bydate) {
    foreach ($r as $item) {
        $results[$bydate][$item['marketplace']] = [
            'total_orders' => $item['total_orders'],
            'total_stickers' => $item['total_stickers'],
            'total_value' => $item['total_value']
        ];
    }
}

But the result is that although the structure looks right now the data itself is the same for every day (not using the data for that day).

Here is the resulting array

Array
(
    [2020-09-06] => Array
        (
            [Etsy] => Array
                (
                    [total_orders] => 2
                    [total_stickers] => 3
                    [total_value] => 7.83
                )

            [Woo] => Array
                (
                    [total_orders] => 10
                    [total_stickers] => 20
                    [total_value] => 100.38
                )

            [eBay] => Array
                (
                    [total_orders] => 17
                    [total_stickers] => 18
                    [total_value] => 67.36
                )

        )

    [2020-09-07] => Array
        (
            [Etsy] => Array
                (
                    [total_orders] => 2
                    [total_stickers] => 3
                    [total_value] => 7.83
                )

            [Woo] => Array
                (
                    [total_orders] => 10
                    [total_stickers] => 20
                    [total_value] => 100.38
                )

            [eBay] => Array
                (
                    [total_orders] => 17
                    [total_stickers] => 18
                    [total_value] => 67.36
                )

        )
)

I now need to get it it show the correct data for the day.


Solution

  • Try this, use array_column to pick out the dates, loop over them, then use array_filter to filter only the items with the date, then add the item to the array using the marketplace as the key.

    <?php
    $data = [
        ['id' => 1, 'date_inserted' => '2020-09-06', 'marketplace' => 'Etsy', 'total_stickers' => 11, 'total_orders' => 8, 'total_value' => 41.619999999999997],
        ['id' => 2, 'date_inserted' => '2020-09-06', 'marketplace' => 'Woo', 'total_stickers' => 2, 'total_orders' => 1, 'total_value' => 7.9800000000000004],
        ['id' => 3, 'date_inserted' => '2020-09-06', 'marketplace' => 'eBay', 'total_stickers' => 44, 'total_orders' => 40, 'total_value' => 115.63],
        ['id' => 4, 'date_inserted' => '2020-09-07', 'marketplace' => 'Etsy', 'total_stickers' => 8, 'total_orders' => 4, 'total_value' => 34.920000000000002],
        ['id' => 5, 'date_inserted' => '2020-09-07', 'marketplace' => 'Woo', 'total_stickers' => 9, 'total_orders' => 3, 'total_value' => '52.90'],
        ['id' => 6, 'date_inserted' => '2020-09-07', 'marketplace' => 'eBay', 'total_stickers' => 23, 'total_orders' => 21, 'total_value' => 58.030000000000001]
    ];
    
    $result = [];
    foreach (array_column($data, 'date_inserted') as $date) {
        foreach (array_filter($data, function($v) use ($date) { 
            return $v['date_inserted'] === $date; 
        }) as $item) {
            $result[$date][$item['marketplace']] = [
                'id' => $item['id'],
                'total_stickers' => $item['total_stickers'],
                'total_orders' => $item['total_orders'],
                'total_value' => $item['total_value']
            ];
        }
    }
    
    print_r($result);
    

    Result:

    Array
    (
        [2020-09-06] => Array
            (
                [Etsy] => Array
                    (
                        [id] => 1
                        [total_stickers] => 11
                        [total_orders] => 8
                        [total_value] => 41.62
                    )
    
                [Woo] => Array
                    (
                        [id] => 2
                        [total_stickers] => 2
                        [total_orders] => 1
                        [total_value] => 7.98
                    )
    
                [eBay] => Array
                    (
                        [id] => 3
                        [total_stickers] => 44
                        [total_orders] => 40
                        [total_value] => 115.63
                    )
    
            )
    
        [2020-09-07] => Array
            (
                [Etsy] => Array
                    (
                        [id] => 4
                        [total_stickers] => 8
                        [total_orders] => 4
                        [total_value] => 34.92
                    )
    
                [Woo] => Array
                    (
                        [id] => 5
                        [total_stickers] => 9
                        [total_orders] => 3
                        [total_value] => 52.90
                    )
    
                [eBay] => Array
                    (
                        [id] => 6
                        [total_stickers] => 23
                        [total_orders] => 21
                        [total_value] => 58.03
                    )
    
            )
    
    )
    

    https://3v4l.org/QnHQf