Take the 2-minute tour ×
Stack Overflow is a question and answer site for professional and enthusiast programmers. It's 100% free, no registration required.

I'm trying to insert high level product review data to SKU records but am stuck with trying to get the average value of duplicated keys.

Array
(
    [0] => Array
        (
            [sku] => 70835
            [rating] => 5
        )

    [1] => Array
        (
            [sku] => F6W/35
            [rating] => 5
        )

    [2] => Array
        (
            [sku] => 36865
            [rating] => 5
        )

    [3] => Array
        (
            [sku] => 36835
            [rating] => 5
        )

    [4] => Array
        (
            [sku] => F30W/T8/830/POLYLUX
            [rating] => 2
        )

    [5] => Array
        (
            [sku] => 70835
            [rating] => 4
        )
)

I would like to get the average rating for the duplicate skus so expected output would be:

Array
(
    [0] => Array
        (
            [sku] => 70835
            [rating] => 4.5
        )

    [1] => Array
        (
            [sku] => F6W/35
            [rating] => 5
        )

    [2] => Array
        (
            [sku] => 36865
            [rating] => 5
        )

    [3] => Array
        (
            [sku] => 36835
            [rating] => 5
        )

    ...
)

I have the below loop which is summing the duplicates but I'm struggling to get the average

foreach ($reviews as $val) {
    if (!isset($result[$val['sku']]))
    {
        $result[$val['sku']] = $val;
    }
    else{
        $result[$val['sku']]['rating'] += $val['rating'];
        #This will sum the duplicated ratings but I need to divide the sum here by the number of times the 'sku' index was duplicated so in the example 9/2 = 4.5
    }
}

thanks in advance!

share|improve this question
1  
How are you retrieving the data? This could be done easily at database level (providing that's where the data comes from) –  billyonecan Jun 9 at 9:38

3 Answers 3

up vote 0 down vote accepted

What about adding a count field to your result array...

foreach ($reviews as $val) {
    if (!isset($result[$val['sku']]))
    {
        $result[$val['sku']] = $val;
        $result[$val['sku']]["count"] = 1;
    }
    else{
        $result[$val['sku']]['rating'] += $val['rating'];
        $result[$val['sku']]["count"] ++;
    }
}

foreach($result as $k => $v) {
    $result[$k]['avg'] = $v['rating']/$v['count'];
}
share|improve this answer
    
You're setting $result[$val['sku']] to $val, and then you're trying to edit an array index (count on $result[$val['sku']]) on a non array. –  FrankerZ Jun 9 at 9:43
    
$val is an array, so it should work –  steven Jun 9 at 9:46
    
Yeah, my bad. Make a quick edit to your post, and I'll remove the downvote. (Although, I'm hesitant to put more redundant data in the array (IE. SKU, when it's already the key), but that's just me.) –  FrankerZ Jun 9 at 9:48

This should work for you:

foreach ($reviews as $val) {
    if (!isset($result[$val['sku']]))
    {
        $result[$val['sku']] = array('rating' => $val['rating'], 'count' => 1);
    }
    else{
        $result[$val['sku']]['rating'] += $val['rating'];
        $result[$val['sku']]['count']++;
    }
}

foreach ($result as &$val) {
    $val['average'] = $val['rating'] / $val['count'];
}

Be aware, if this data is coming from a database, there are much easier ways to do this, by using GROUP BY statements.

share|improve this answer
    
$val in first loop is an array so you cannot do: $result[$val['sku']]['val'] += $val['rating']; –  steven Jun 9 at 9:44
    
Updated my answer, and made variables clearer. –  FrankerZ Jun 9 at 9:48
    
yes, I saw. I think both answers should work now –  steven Jun 9 at 9:49
    
Thanks guys, both answers work. FYI the data source is a JSON feed which I had split down to that stage. Thanks again for the help I was pulling what's left of my hair out with that one! –  Paulus Jun 10 at 8:18
[akshay@localhost tmp]$ cat test.php
<?php

$array = array (
  0 => 
  array (
    'sku' => '70835',
    'rating' => '5',
  ),
  1 => 
  array (
    'sku' => 'F6W/35',
    'rating' => '5',
  ),
  2 => 
  array (
    'sku' => '36865',
    'rating' => '5',
  ),
  3 => 
  array (
    'sku' => '36835',
    'rating' => '5',
  ),
  4 => 
  array (
    'sku' => 'F30W/T8/830/POLYLUX',
    'rating' => '2',
  ),
  5 => 
  array (
    'sku' => '70835',
    'rating' => '4',
  ),
);

$final=$count=array();

foreach($array as $v)
{
    if(isset($final[$v['sku']]))
    {
      $final[$v['sku']]['rating'] += $v['rating'];
      $count[$v['sku']]++;
    }else
    {
      $final[$v['sku']] = $v;
      $count[$v['sku']] = 1;
    }

}

array_map( function($a, $b) use (&$final){ $final[$a]['rating']/=$b; }, array_keys($count),array_values($count));
unset($count);

// Input
print_r($array);

// Output
print_r( array_values($final));

?>

Output

[akshay@localhost tmp]$ php test.php
Array
(
    [0] => Array
        (
            [sku] => 70835
            [rating] => 5
        )

    [1] => Array
        (
            [sku] => F6W/35
            [rating] => 5
        )

    [2] => Array
        (
            [sku] => 36865
            [rating] => 5
        )

    [3] => Array
        (
            [sku] => 36835
            [rating] => 5
        )

    [4] => Array
        (
            [sku] => F30W/T8/830/POLYLUX
            [rating] => 2
        )

    [5] => Array
        (
            [sku] => 70835
            [rating] => 4
        )

)
Array
(
    [0] => Array
        (
            [sku] => 70835
            [rating] => 4.5
        )

    [1] => Array
        (
            [sku] => F6W/35
            [rating] => 5
        )

    [2] => Array
        (
            [sku] => 36865
            [rating] => 5
        )

    [3] => Array
        (
            [sku] => 36835
            [rating] => 5
        )

    [4] => Array
        (
            [sku] => F30W/T8/830/POLYLUX
            [rating] => 2
        )

)
share|improve this answer
    
It's a very bad habit to not initialize arrays ($count) before you write to them. –  FrankerZ Jun 9 at 15:49
    
Initialised as you suggested –  Akshay Hegde Jun 9 at 17:28

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.