0

So I am pretty lost here because I don't know what my object looks like (not sure why I can't do print_r() to print the object).

Basically from the below code, I need to sort the reviews which is $_reviews based on $percent_avg. I got the $percent_avg value from a multiple for loops and that's what complicates things. I am not sure how can I make a new sorted array based on that $percent_avg variable.

$_reviews = $block->getReviewCollection($_item->getID());
$sorted_reviews = [];
$sorted_percentage = [];
foreach ($_reviews as $_review) {
    $total_percent = 0;
    foreach ($_review->getRatingVotes() as $_vote){
        $total_percent += $_vote->getPercent();
    }
    $percent_avg = $total_percent/3;
    array_push($sorted_percentage, $percent_avg);
}

I have attempted the above code to sort the reviews, what I think is that I can make a new array for a sorted $percent_avg and compare that value with the $_reviews object? But with this, it will be pretty slow?

//sort array
sort($sorted_percentage);

//run a for loop - if the value in $sorted_percentage matches $percent_avg, push it to a new array
foreach ($sorted_percentage as $percent) {
                foreach ($_reviews as $_review) {
                    $total_percent = 0;
                    foreach ($_review->getRatingVotes() as $_vote){
                        $total_percent += $_vote->getPercent();
                    }
                    $percent_avg = $total_percent/3;
                    if($percent_avg == $percent){
                        array_push($sorted_reviews, $_review);
                    }
                }
            }

The above is just an idea and it is not working.

I am still new to PHP, so any suggestions/helps will be appreciated. Thank you.

Student04
  • 55
  • 6
  • 1
    Can you rather show the array at hand and from which array perspective you would like to sort it with ? A var_export() of your arrays in your post would be pretty helpful. – nice_dev Dec 16 '20 at 04:42
  • Because you don't know how the array looks, the answer could be almost anything on this page. https://stackoverflow.com/questions/17364127/how-can-i-sort-arrays-and-data-in-php If dealing with a percentage, read this https://stackoverflow.com/questions/9041909/php-sorting-array-values-from-within-an-array – react_or_angluar Dec 16 '20 at 04:49
  • So you want to sort by: ( sum of each review's `getRatingVotes()` ) / 3? – kmoser Dec 16 '20 at 04:51
  • This might help https://stackoverflow.com/questions/1597736/how-to-sort-an-array-of-associative-arrays-by-value-of-a-given-key-in-php – react_or_angluar Dec 16 '20 at 04:55
  • @kmoser yes, that's correct – Student04 Dec 16 '20 at 05:10
  • @Student04 Why bother dividing by 3? That just takes more time and is more complicated, and won't make a difference in the end result. – kmoser Dec 16 '20 at 05:10

1 Answers1

1

If you want to sort $_reviews based on the sum of each review's getRatingsVotes()' getPercent(), you can use usort():

usort( $_reviews, function( $a, $b ) {
    $a_total = 0;
    foreach ( $a->getRatingVotes() as $_vote ) {
        $a_total += $_vote->getPercent();
    }

    $b_total = 0;
    foreach ( $b->getRatingVotes() as $_vote ) {
        $b_total += $_vote->getPercent();
    }

    return $a_total <=> $b_total;
});

This may be slow if $_reviews contains many elements, or if individual reviews tend to contain many votes. You can speed it up by caching $a_total and $b_total, and using those cached numbers where possible:

usort( $_reviews, function( $a, $b ) {
    if ( array_key_exists( 'total', $a ) ) {
        // Fetch from cache:
        $a_total = $a['total'];
    } else {
        // Calculate and store in cache:
        $a_total = 0;
        foreach ( $a->getRatingVotes() as $_vote ) {
            $a_total += $_vote->getPercent();
        }
        $a['total'] = $a_total;
    }

    if ( array_key_exists( 'b_total', $b ) ) {
        // Fetch from cache:
        $b_total = $b['total'];
    } else {
        // Calculate and store in cache:
        $b_total = 0;
        foreach ( $b->getRatingVotes() as $_vote ) {
            $b_total += $_vote->getPercent();
        }
        $b['total'] = $b_total;
    }

    return $a_total <=> $b_total;
});
kmoser
  • 8,780
  • 3
  • 24
  • 40
  • Thank you so much for this! If you don't mind, could you please explain a little bit about the first code? Specifically, I don't understand why would there be `function($a, $b)`, how does $a and $b come from? Sorry stupid question but I am still learning :) – Student04 Dec 16 '20 at 16:34
  • PHP's [`usort()`](https://www.php.net/manual/en/function.usort.php) accepts a callback function which will be passed two array elements (this happens automatically by PHP), and whose job it is to return a number indicating which has the higher value. In my code, the callback is an anonymous function (i.e. unnamed), and I have arbitrarily named the parameters `$a` and `$b`. You may change those names to anything you wish. See the `usort()` documentation for more details on the callback function and how it is expected to work. – kmoser Dec 17 '20 at 05:01