# php - Get highest and lowest values from an array where order is like "AAA", "AA", "A", "BBB", "BB", etc

281

What I'm trying to do is creating a custom rating system like this:

``````AAA - Highest rating
AA
A
BBB
BB
B
CCC
CC
C - Lowest rating
``````

In which AAA is the highest and C the lowest. For this this to work I need PHP to know which rating is the highest, lowest and everything in between and evaluate series of ratings based on that. I allready figured out how to create a sorting with`usort()` like so:

``````\$ratings = array("a" => "AAA", "b" => "AA", "c" => "A", "d" => "BBB", "e" => "BB", "f" => "B", "g" => "CCC", "h" => "CC", "i" => "C");
\$sortedRatings = usort(\$ratings, "cmp_function");
``````

This will return an array neatly sorted from highest priority to lowest. Now I need to go ahead and use this sorting to get the highest and lowest rating from an array like this one:

``````\$ratingHistory = array("BB", "B", "CCC", "C", "BB");
``````

So how could I go about getting the highest and lowest value from`\$ratingHistory` based on the sorting as in`\$sortedRatings` ? I hope someone can help me out with this one. If my problem isn't completely clear to you, drop a comment so I can try to explain further.

Edit:

Just to be clear. The expected outcomes would be:

``````Highest: BB
Lowest: C
``````
754

#### Solution:

This solution works with your original`\$ratings` array and — through`usort()` — sort`\$ratingHistory`:

``````\$ratings = array("a" => "AAA", "b" => "AA", "c" => "A", "d" => "BBB", "e" => "BB", "f" => "B", "g" => "CCC", "h" => "CC", "i" => "C");
\$ratingHistory = array("BB", "B", "CCC", "C", "BB");

usort
(
\$ratingHistory,
function( \$a, \$b ) use( \$ratings )
{
return strcmp( array_search( \$a, \$ratings ), array_search( \$b, \$ratings ) );
}
);

\$result = array( 'max'=>current(\$ratingHistory), 'min'=>end(\$ratingHistory) );

print_r( \$result );
``````

Will print:

``````Array
(
[max] => BB
[min] => C
)
``````

### Performance:

I have compared the performance of above example with a`foreach()`, an`array_map()` (all cases with both associative and enumerated array as`\$ratings` and with different`\$ratingHistory` sizes). The`usort()` method is in anyhow far the more efficient. This because you have anyway to iterate complete array, but with`usort` you can use less commands/functions/comparisons.

326

#### Solution:

You can try this code :

``````\$ratings = array("", "AAA","AA", "A", "BBB", "BB", "B", "CCC", "CC", "C");
\$ratingHistory = array("BB", "B", "CCC", "C", "BB");

\$min = 0;
\$max = INF;
foreach (\$ratingHistory as \$row)
{
\$rate = array_search(\$row, \$ratings);
if (\$rate && \$rate > \$min) {
\$min = \$rate;
}
if (\$rate && \$rate < \$max) {
\$max = \$rate;
}
}

echo 'Min : '. \$ratings[\$min];
echo '<br />Max : '. \$ratings[\$max];
``````

If you test, the values are BB and C for your example.

734

#### Solution:

Because ALL of your encounterable values are in your ratings lookup array, you can enjoy the sweet brevity of`array_intersect()`. This will remove all values from the`\$ratings` array which are not found in the`\$ratingsHistory` array. Of course, the`\$ratings` array is already in order, so the results are instantly accessible from the first and last elements.

Code: (Demo)

``````\$ratingHistory = array_intersect(\$ratings, \$ratingHistory);
var_export([
'min' => \$ratingHistory[key(\$ratingHistory)],
'max' => \$ratingHistory[array_key_last(\$ratingHistory)]
]);
``````

If you don't want to maintain a lookup array (to allow your code to be more dynamic/robust and require less maintenance), spell out the logic. Using a linear foreach loop will have a smaller time complexity and will offer better performance than a non-linear sort like`usort()`.

Code: (Demo)

``````\$result = ['min' => null, 'max' => null];
foreach (\$array as \$value) {
if (
!\$result['min']
|| (!trim(\$value, \$result['min']) ? \$value < \$result['min'] : \$value > \$result['min'])
) {
\$result['min'] = \$value;
}
if (
!\$result['max']
|| (!trim(\$value, \$result['max']) ? \$value > \$result['max'] : \$value < \$result['max'])
) {
\$result['max'] = \$value;
}
}
var_export(\$result);
``````

Maintaining a lookup array for priorities and calling`usort()` is also a clean approach, but this has been asked before on Stack Overflow and it will have the poorest time complexity score of these three snippets. 1 2 3 4

Code: (Demo)

``````\$lookup = array_flip(\$ratings);
usort(\$ratingHistory,  fn(\$a, \$b) => \$lookup[\$a] <=> \$lookup[\$b]);
var_export([
'min' => \$ratingHistory,
'max' => \$ratingHistory[array_key_last(\$ratingHistory)]
]);
``````

P.s. Any technique that is making iterated calls of`array_search()` will have worse performance than ALL of my snippets above. "Value searching" an array is always going to be slower than "key searching" an array in PHP.

People are also looking for solutions to the problem: batch file - Plink fails to run when executed from PHP in wamp, but works when executed manually

Source