3

I have a two-dimensional array containing names and integer values. The rows do not consistently contain all names. I need to group the data by name and find the average of all values in each group.

Sample array:

$games = [
    [
        "Armstrong_Tony" => 7,
        "Blair_Jarryd" => 7,
        "Broomhead_Tim" => 11
    ],
    [
        "Armstrong_Tony" => 19,
        "Ball_Luke" => 20,
        "Blair_Jarryd" => 20,
        "Broomhead_Tim" => 23
    ],
    [
        "Ball_Luke" => 20,
        "Beams_Dayne" => 14,
        "Blair_Jarryd" => 19,
        "Frost_Jack" => 8,
        "Goldsack_Tyson" => 7
    ]
];

Desired result:

[
  'Armstrong_Tony' => 13,
  'Blair_Jarryd' => 15.333333333333334,
  'Broomhead_Tim' => 17,
  'Ball_Luke' => 20,
  'Beams_Dayne' => 14,
  'Frost_Jack' => 8,
  'Goldsack_Tyson' => 7,
]

My coding attempt:

$arr = array_merge_recursive($games[0],$games[1],$games[2],$games[3],$games[4]);
ksort($arr);

foreach($arr as $player => $val) {

    if(array_key_exists($player, $games[0])) {
        $prev_game_0 = $games[0][$player];
    } else {
        $prev_game_0 = "";
    }
    if(array_key_exists($player, $games[1])) {
        $prev_game_1 = $games[1][$player];
    } else {
        $prev_game_1 = "";
    }
    if(array_key_exists($player, $games[2])) {
        $prev_game_2 = $games[2][$player];
    } else {
        $prev_game_2 = "";
    }
    if(array_key_exists($player, $games[3])) {
        $prev_game_3 = $games[3][$player];
    } else {
        $prev_game_3 = "";
    }
    if(array_key_exists($player, $games[4])) {
        $prev_game_4 = $games[4][$player];
    } else {
        $prev_game_4 = "";
    }

    $last_5_array[$player] = array($prev_game_0, $prev_game_1, $prev_game_2, $prev_game_3, $prev_game_4);
}
mickmackusa
  • 43,625
  • 12
  • 83
  • 136
user537137
  • 606
  • 2
  • 10
  • 23

3 Answers3

2

This should work for you to get all keys and all averages:

Here i go through each innerArray and get all key values after saving them in a array i flatter the array and only take unique values

After that i use array_column() (For PHP +5.5), count() and array_sum() to calculate the average.

<?php

    $arr = array(
                array(
                    "Armstrong_Tony" => 7,
                    "Blair_Jarryd" => 7,
                    "Broomhead_Tim" => 11
                ),
                array(
                    "Armstrong_Tony" => 19,
                    "Ball_Luke" => 20,
                    "Blair_Jarryd" => 20,
                    "Broomhead_Tim" => 23
                ),
                array(
                    "Ball_Luke" => 20,
                    "Beams_Dayne" => 14,
                    "Blair_Jarryd" => 19,
                    "Frost_Jack" => 8,
                    "Goldsack_Tyson" => 7
                )
        );

    $keys = array();
    $average = array();

    //Get Keys
    foreach($arr as $innerArray)
        $keys[] = array_keys($innerArray);

    $keys = array_unique(call_user_func_array('array_merge', $keys));


    //Get average
    foreach($keys as $key) {
        $values = array_column($arr, $key);
        $average[$key] = array_sum($values) / count($values);
    }

    print_r($average);

?>

Output:

Array
(
    [Armstrong_Tony] => 13
    [Blair_Jarryd] => 15.333333333333
    [Broomhead_Tim] => 17
    [Ball_Luke] => 20
    [Beams_Dayne] => 14
    [Frost_Jack] => 8
    [Goldsack_Tyson] => 7
)
Rizier123
  • 58,877
  • 16
  • 101
  • 156
1

You need to create an array that contains both the sum and the count (# of times a key appears across all arrays) for each key. Once you've compiled that information loop through the array and divide the sum by the count to get the average.

$myArrays = array(
    array('Armstrong_Tony' => 2),
    array('Ball_Luke' => 3),
);

$sums = array();

foreach($myArrays as $array) {
    foreach($array as $key => $value) {
        if(!isset($sums[$key]))
            $sums[$key] = array('count' => 0, 'sum' => 0);

        $sums[$key]['count']++;
        $sums[$key]['sum'] += $value;
    }
}

$results = array();

foreach($sums as $key => $sum) {
    $results[$key] = $sum['sum']/$sum['count'];
}

print_r($results);
FuzzyTree
  • 32,014
  • 3
  • 54
  • 85
1

For a modern elegant approach begin by using array_merge_recursive() with the spread operator to group the data by associative key. Then, inside array_map() cast the group's data to be an array (because solitary values are not formed into subarrays). Then make the standard calls of array_sum() and count().

Code: (Demo)

var_export(
    array_map(
        function($data) {
            $data = (array) $data;
            return array_sum($data) / count($data);
        },
        array_merge_recursive(...$array)
    )
);

Or with PHP7.4's arrow functions:

var_export(
    array_map(
        fn($data) => array_sum((array) $data) / count((array) $data),
        array_merge_recursive(...$array)
    )
);
mickmackusa
  • 43,625
  • 12
  • 83
  • 136