brico
brico

Reputation: 61

php array and averaging

I would like to switch from array 1 to array 2 according to the model below

I'm stuck on the implementation of item averages

the lessons, the number of notes and the order of the notes are random

Array 1

$tabAsso  =

Array
(
    [51] => Array
        (
            [id] => 51
            [name] => JOHN
            [studies] => Array
                (
                    [0] => math
                    [1] => LV1
                    [2] => math
                    [3] => LV1
                    [4] => history
                    [5] => history
                )
            [notesC] => Array
                (
                    [0] => 12
                    [1] => 18
                    [2] => 28
                    [3] => 45
                    [4] => 10
                    [5] => 18
                )
            [denumsC] => Array
                (
                    [0] => 15
                    [1] => 60
                    [2] => 40
                    [3] => 75
                    [4] => 12
                    [5] => 45
                )
        )
    [52] => Array
        (
            [id] => 52
            [name] => PETER
            [studies] => Array
                (
                    [0] => sport
                    [1] => tech
                    [2] => sport
                    ...

For example for the math average, you must read :

notesC: sum (12 + 28)

denumC sum (15 +40)

then average : (40/55) *20 = 14.5

I would like to reach this array 2

    [51] => Array
        (
            [id] => 51
            [name] => JOHN
            [studies] => Array
                (
                    [0] => math
                    [1] => LV1
                    [2] => history
                )
            [averages] => Array
                (
                    [0] => 14.5
                    [1] => 9.3
                    [2] => 9.8
                )

        )
    [52] => Array
        (
            [id] => 52
            [name] => PETER
            [studies] => Array
                (
                    [0] => sport
                    [1] => tech

                )
            [averages] => Array
                (
                    [0] => xx
                    [1] => xx
                )

        )
     ...

So far I have managed to do this ...

        $tabAssoForBar = [];

        foreach ($tabAsso as $id => $t) {

            foreach ($t['studies'] as $k => $m) {

                if (!array_key_exists($id, $tabAssoForBar)) {
                    $tabAssoForBar[$id] = [
                        'id'     => $id,
                        'name'    => $t['name'],
                    ];
                    $tabAssoForBar[$id]['studies']  = [$m];
                } else {
                    if (!in_array($m, $tabAssoForBar[$id]['studies'])) {
                        $tabAssoForBar[$id]['studies'][] = $m;
                    } else {
                        // nothing
                    }
                }
            }
        };

I return studies with only 3 fields (math, LV1, history) but cannot create the averages field

Thanks for your help

Upvotes: 1

Views: 55

Answers (1)

The fourth bird
The fourth bird

Reputation: 163277

You might use an approach to get all the indices from "study" for a all the unique values, and get the values from "notesC" and "denumsC" for those corresponding indices.

Then per unique value for "study", first sum them separately for "notesC" and "denumsC" and then divide those results and multiply the outcome by 20 to fulfill this formula:

(40/55) *20 = 14.5

You can create the result array by using the current index as the index in the new array and the unique studies and averages to it.

For example

$tabAssoForBar = [];

foreach ($tabAsso as $id => $t) {
    
    $uniqueStudies = array_unique($t['studies']);
    $averages = [];
    
    foreach ($uniqueStudies as $uniqueStudy) {
        
        $keysFromStudies = array_keys(array_filter($t['studies'], function($x) use ($uniqueStudy) {
            return $x === $uniqueStudy;
        }));
        
        $averages[] = round(
            (
                array_sum(array_intersect_key($t['notesC'], array_flip($keysFromStudies))) /
                array_sum(array_intersect_key($t['denumsC'], array_flip($keysFromStudies)))
            ) * 20,
            1
        );
    }
    $tabAssoForBar[$id] = [
        'id' => $t['id'],
        'name' => $t['name'],
        'studies' => array_values($uniqueStudies),
        'averages' => $averages
    ];
}

print_r($tabAssoForBar);

Output

Array
(
    [51] => Array
        (
            [id] => 51
            [name] => JOHN
            [studies] => Array
                (
                    [0] => math
                    [1] => LV1
                    [2] => history
                )

            [averages] => Array
                (
                    [0] => 14.5
                    [1] => 9.3
                    [2] => 9.8
                )

        )

)

See a php demo

Upvotes: 1

Related Questions