Reputation: 1386
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
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
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
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
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