GotBatteries
GotBatteries

Reputation: 1386

PHP, How to find next greater key value from array

I have an array like this:

$pricing = array(
                 "2" => 8.23,
                 "5" => 10.97,
                 "10" => 13.28,
                 "15" => 15.40,
                 "20" => 18.15,
                 "25" => 20.36,
                 "30" => 22.84,
                 "40" => 25.60,
                 "50" => 28.35,
                 "60" => 31.89,
                 "70" => 36.23,
                 "80" => 39.40,
                 "90" => 42.52,
                 "100" => 44.75
                );

And I have a variable that has the client given value from 1 to 100.

Question is: what is the best and fastest way to find the next biggest key, if the key itself doesn't exist?

E.g. I have a variable with value of 12, and I need to get the price for that. According to the array here, the price would be 15.40 because the next biggest key is 15.

I could try and find key number '12', and if it doesn't exist, i would add one(12+1) and try again, until next key is found, but is there any function that could do this for me, or something even better/faster?

Edit: Clarification about the structure of the array.

Array is like it is in the example here. Keys are ordered as can be seen.

Upvotes: 1

Views: 2106

Answers (4)

mickmackusa
mickmackusa

Reputation: 47904

Your lookup array will not change so it makes perfect sense to declare it as a constant (instead of a variable) and to make your code immediately understandable, give the constant a self-explanatory name.

const THRESHOLD_PRICES = [
    2 => 8.23,
    5 => 10.97,
    10 => 13.28,
    15 => 15.40,
    20 => 18.15,
    25 => 20.36,
    30 => 22.84,
    40 => 25.60,
    50 => 28.35,
    60 => 31.89,
    70 => 36.23,
    80 => 39.40,
    90 => 42.52,
    100 => 44.75
];

A valuable benefit of using a constant is that it is not necessary to explicitly pass the data into a function's scope.

In your function, I recommend type hinting the parameter and the return value -- again to make the code easier to understand.

Before iterating the array, do a quick scan of the keys for an exact match. Because of the way that php treats arrays as hashmaps, this is a very low-cost technique.

Next iterate the array and break the loop as soon as the array key is larger than the search value.

Regardless of if/when the loop breaks, the final iteration will declare the targeted price, so unconditionally return that float value.

function getThresholdPrice(int $search): float {
    if (isset(THRESHOLD_PRICES[$search])) {
        return THRESHOLD_PRICES[$search];
    }
    foreach (THRESHOLD_PRICES as $threshold => $price) {
        if ($threshold > $search) {
            break;
        }
    }
    return $price;
}

Tests: (Demo)

foreach (range(1, 105, 13) as $test) {
    printf("%d => %.02f\n", $test, getThresholdPrice($test));
}

Output:

1 => 8.23
14 => 15.40
27 => 22.84
40 => 25.60
53 => 31.89
66 => 36.23
79 => 39.40
92 => 44.75
105 => 44.75

Upvotes: 0

Ja͢ck
Ja͢ck

Reputation: 173572

A simple foreach will do, but to guard against either empty arrays or a needle that's higher than the highest key, here's an implementation that will cover that as well:

function find(array $pricing, $needle)
{
    $last = null; // return value if $pricing array is empty

    foreach ($pricing as $key => $value) {
        if ($key >= $needle) {
            return $key; // found it, return quickly
        }
        $last = $key; // keep the last key thus far
    }

    return $last;
}

$result = find($pricing, 12); // 15
$result = find($pricing, 101); // 100
$result = find([], 12); // null

Upvotes: 2

Dezigo
Dezigo

Reputation: 3256

Your logic is ok, you can do it using next() http://php.net/manual/en/function.next.php

$search = 12;
$pricing = array(
                 "2" => 8.23,
                 "5" => 10.97,
                 "10" => 13.28,
                 "15" => 15.40,
                 "20" => 18.15,
                 "25" => 20.36,
                 "30" => 22.84,
                 "40" => 25.60,
                 "50" => 28.35,
                 "60" => 31.89,
                 "70" => 36.23,
                 "80" => 39.40,
                 "90" => 42.52,
                 "100" => 44.75
                );

$result = null;
if (!isset($pricing[$search])) {
  do {
   } while (next($pricing) && $search > key($pricing));
    $result = current($pricing);
} else {
   $result = $pricing[$search];
}

echo $result;

Upvotes: -1

Ryan Vincent
Ryan Vincent

Reputation: 4513

Assuming you are looking for the 'requiredKey' and that the array is sorted by key

This seem to do what you want.

Code:

<?php

$pricing = array(
                 "2" => 8.23,
                 "5" => 10.97,
                 "10" => 13.28,
                 "15" => 15.40,
                 "20" => 18.15,
                 "25" => 20.36,
                 "30" => 22.84,
                 "40" => 25.60,
                 "50" => 28.35,
                 "60" => 31.89,
                 "70" => 36.23,
                 "80" => 39.40,
                 "90" => 42.52,
                 "100" => 44.75
                );

// What key we want...
$requiredKey =  12;

// outout in here
$foundKey   = -1;
$foundValue = -1;

// always run the loop once...
do {
    $foundKey = key($pricing);        // store the current details
    $foundValue = current($pricing);

    next($pricing); // will be equal or greater
}
while (   current($pricing) !== false
        && $foundKey < $requiredKey);


echo '<pre>';
echo '<br />', 'key: ', $foundKey, ' value: ',  $foundValue;
echo '</pre>';

Output:

key: 15 value: 15.4

Upvotes: 1

Related Questions