What is the most performative way to group data from a PHP array?

Asked

Viewed 171 times

0

I have an array that was generated by Database Query Builder of Laravel 5.1.x.

array:96 [▼
  0 => {#1256 ▼
    +"customer_id": 58
    +"city": "Rio de Janeiro"
    +"program_id": 3
    +"program": "PROGRAMA XPTO"
    +"subregion": "SUB-REGIÃO UM"
    +"mr_name": "2015/02"
    +"info_1": 8
    +"info_2": 9
    +"info_3": 239
    +"info_4": 10
    +"info_5": 295
    +"info_6": "12.3430962343096"
  }
  1 => {#1255 ▼
    +"customer_id": 58
    +"city": "Rio de Janeiro"
    +"program_id": 3
    +"program": "PROGRAMA XPTO"
    +"subregion": "SUB-REGIÃO UM"
    +"mr_name": "2015/03"
    +"info_1": 8
    +"info_2": 9
    +"info_3": 239
    +"info_4": 21
    +"info_5": 377
    +"info_6": "7.51145646543136"
  }
  2 => {#1254 ▼
    +"customer_id": 58
    +"city": "Rio de Janeiro"
    +"program_id": 3
    +"program": "PROGRAMA XPTO"
    +"subregion": "SUB-REGIÃO UM"
    +"mr_name": "2015/04"
    +"info_1": 8
    +"info_2": 9
    +"info_3": 239
    +"info_4": 19
    +"info_5": 607
    +"info_6": "13.3670997577626"
  }
  ...
]

My problem => I need to group the information of this array as follows:

array: [▼
    "customers" => { ▼
        +"Rio de Janeiro": array [▼
            +"programs": array [▼
                "PROGRAMA XPTO": array [▼
                    +"subregions": array [▼
                        "SUB-REGIÃO UM": array [▼
                            "months": array [▼
                                "2015/02": array [],
                                "2015/03": array [],
                                "2015/04": array [],
                                "2015/05": array [],
                                "2015/06": array [],
                                "2015/07": array [],
                                ...
                            ]
                        ]
                    ]
                ]
            ]
        ]
    ]
  ...
]

Using pure PHP and iterating each array value, I had a 5 to 10 second increase in method execution/rendering (code below):

if (!empty($result)) {
    $city = $result[0]->city;
    $program = null;
    $subregion = null;
    $school = null;
    $class = null;

    $data['customers'] = [];

    foreach ($result as $r => $row) {
        if (isset($data[$row->city])) {
            continue;
        }

        $city = $row->city;
        $data['customers'][$city] = [];
        $data['customers'][$city]['customer_id'] = $row->customer_id;

        foreach ($result as $pid => $programs) {
            if ($city == $programs->city) {
                if (isset($data[$city]['programs'][$programs->program])) {
                    continue;
                }

                $program = $programs->program;

                $data['customers'][$city]['programs'][$program] = [
                    'program_id' => $programs->program_id,
                    'total_escolas' => false,
                    'total_turmas' => false,
                    'students' => false,
                    'subregions' => []
                ];

                foreach ($result as $subId => $subregions) {
                    if (($city == $subregions->city)
                        and ($program == $subregions->program)
                    ) {
                        $subregion = $subregions->subregion;
                        $data['customers'][$city]['programs'][$program]['subregions'][$subregions->subregion] = [
                            'months' => []
                        ];

                        foreach ($result as $mId => $months) {
                            if (($city == $months->city)
                                and ($program == $months->program)
                                and ($subregion == $months->subregion)
                                and !empty($data['customers'][$city]['programs'][$program]['subregions'][$subregion]['months'][$months->mr_name])
                            ) {
                                $mr_name = $months->mr_name;
                                $data['customers'][$city]['programs'][$program]['subregions'][$subregion]['months'][$mr_name] = [
                                    'info_1' => $months->info_1,
                                    'info_2' => $months->info_2,
                                    'info_3' => $months->info_3,
                                    'info_4' => $months->info_4,
                                    'info_5' => $months->info_5,
                                    'info_6' => $months->info_6
                                ];
                            }
                        }
                    }
                }
            }
        }
    }
}

Note: my query is executed in 137ms and the total execution of the method in average 8 seconds.


So

  • What am I doing wrong? Where is the bottleneck?
  • There is another way to group such data?

If you need more information, let me know.

  • Only query is not enough, post query code Builder.

  • The query Builder and is not the problem. It returns the first array in 137ms. The focus of my doubt is how to group the array. Anyway thank you.

1 answer

0

Solved.

The main problem was a syntax error. Incorrect comparison.

In some places I forgot to add the index ['customers'] in the array:

foreach ($result as $r => $row) {
    // ERRADO - if (isset($data['customers'][$row->city])) { 
    if (isset($data['customers'][$row->city])) {
        continue;
    }

    ...

    foreach ($result as $pid => $programs) {
        if ($city == $programs->city) {
            // ERRADO - if (isset($data[$city]['programs'][$programs->program])) { 
            if (isset($data['customers'][$city]['programs'][$programs->program])) {

Thanks for your help.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.