2

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!

1
  • 1
    How are you retrieving the data? This could be done easily at database level (providing that's where the data comes from) Commented Jun 9, 2015 at 9:38

3 Answers 3

1

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'];
}
Sign up to request clarification or add additional context in comments.

2 Comments

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.
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.)
1

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.

2 Comments

$val in first loop is an array so you cannot do: $result[$val['sku']]['val'] += $val['rating'];
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!
1
[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
        )

)

2 Comments

It's a very bad habit to not initialize arrays ($count) before you write to them.
Initialised as you suggested

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.