1

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

1 Answer 1

1

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

Sign up to request clarification or add additional context in comments.

5 Comments

Thanks this works fine but I need to keep the keys from 0 to .... in ascending order to submit them to chartJs for the field : studies. Now, I read in the documentation (array_unique) : "Note that the keys are preserved. If more than one compared element is equal under the given flags, then the key and value of the first equal element will be kept." The optional second flags parameter can be used to modify sorting behavior but I can't?
@brico Do you mean like this? 3v4l.org/BtDoS I have updated the answer.
Thanks I found doing this
$uniqueStudies = array_values(array_unique($t['studies'])); Congratulations to you
@brico You are welcome, glad you have a solution for your problem :-) Good luck!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.