Monday 3 September 2018

PHP multidimensional array: group repeated values ​​and create & ldquo; sub-array & rdquo;

I have a array with repeated values like this:

Array
(
    [0] => Array
        (
            [id] => 112
            [name] => John
            [country] => Spain
            [age] => 24
            [company] => One
            [price] => 10
        )
    [1] => Array
        (
            [id] => 112
            [name] => John
            [country] => Spain
            [age] => 24
            [company] => Two
            [price] => 15
        )
    [2] => Array
        (
            [id] => 112
            [name] => John
            [country] => Spain
            [age] => 24
            [company] => Three
            [price] => 20
        )
    [3] => Array
        (
            [id] => 224
            [name] => Paul
            [country] => France
            [age] => 25
            [company] => One
            [price] => 25
        )
    [4] => Array
        (
            [id] => 224
            [name] => Paul
            [country] => France
            [age] => 25
            [company] => Two
            [price] => 40
        )
)

I need to group same id with namecountry and age, and make a "sub array" companies with company and price
Array
(
    [112] => Array
        (
            [id] => 112
            [name] => John
            [country] => Spain
            [age] => 24
            [companies] => array (
                                  array(
                                        [company] => One
                                        [price] => 10
                                  )
                                  array(
                                        [company] => Two
                                        [price] => 15
                                  )
                                  array(
                                        [company] => Three
                                        [price] => 20
                                  )
                           )
        )

    [224] => Array
        (
            [id] => 2
            [name] => Paul
            [country] => France
            [age] => 25
            [companies] => array (
                                  array(
                                        [company] => One
                                        [price] => 25
                                  )
                                  array(
                                        [company] => Two
                                        [price] => 40
                                  )
                           )
        )
)

I have tried this code without good results:
$new_array = array();
foreach ($my_array as $item) {
    $new_array[$item['id']][] = $item;
    $new_array[$item['id']]['companies'][] = $item;

}

Then I tried this:
$new_array = array();
foreach ($my_array as $item) {
    $new_array[$item['id']]['temp'] = $item;
    $new_array[$item['id']]['companies'][] = $item;
}

Works fine, but I get temp key that I don't want it. For example, with this code I need to access to id items with $new_array [$key]['temp']['id']
I can remove the temp key with another loop:
$final_array = array();
foreach ($new_array $key=>$item) {
    $final_array [$key] = $item['temp'];
    $final_array [$key]['temp'] = $item['companies'];
}

With this code I can access correctly to id with: $final_array[$key]['id']
Another option is this code:
foreach($array as $v) {
    $result[$v['id']]['id']          = $v['id'];
    $result[$v['id']]['name']        = $v['name'];
    $result[$v['id']]['country']     = $v['country'];
    $result[$v['id']]['age']         = $v['age'];
    $result[$v['id']]['companies'][] = array('company' => $v['company'],
                                             'price'   => $v['price']);
}

But it is not very elegant if we had more keys (phone, email...)
Any ideas?

Nothing wrong with the code you've provided at the end, but here's some ideas for how to make it more tolerant to more array values (as you mentioned, phone, email, etc).
This uses the handy PHP array_diff_key function to remove the array elements you don't want from the "core" records. Then, applying array_diff_key to get those same array elements INTO the "company" records.
// set up the array of keys you don't want in the "original" record
$exclude = ['company' => FALSE, 'price' => FALSE];
// Your original loop
foreach($array as $v) {
    // not strictly necessary, but helps readability
    $id = $v['id'];
    // Assign the "core" record all the values you want, excluding those defined above
    // in this case, will remove "company" and "price"
    $record = array_diff_key( $v, $exclude );

    // only set this if not already set, otherwise wipes out previous companies
    if ( ! isset($result[$id] ) ) {
        $result[$id] = $record;
        $result[$id]['companies'] = [];
    }

    // strip off the OTHER values from the array you don't want stored with the company
    // this will automatically pick up the field NOT excluded above
    // in this case, will remove all BUT "company" and "price"
    $company = array_diff_key( $v, $record );
    $result[$id]['companies'][] = $company;
}

0 comments:

Post a Comment