I have an array with around 3500 array items inside it, the format being below. I have two dynamic variables that change and I need to search the array to find out row price_value based on already knowing price_slot and country.
I've currently got the below but this is taking too long. Is there anyway I can speed up this access?
PHP Function
$country = US;
$priceSlot = 3;
$priceValue = getPriceValue($priceSlot, $country);
function getPriceValue($priceSlot, $country) {
// Search in array for price
foreach ($array as $arrayItem) {
if ($arrayItem['price_slot'] == $priceSlot && $arrayItem['country'] == $country) {
return $arrayItem['price_value'];
}
}
return null;
}
Snippet of Array
Array
(
[0] => Array
(
[price_slot] => 1
[base_price] => Get in Touch
[country] => US
[price_multiplier] =>
[price_value] => Get in Touch
)
[1] => Array
(
[price_slot] => 2
[base_price] => 9000
[country] => US
[price_multiplier] => 1.3
[price_value] => 11700
)
[2] => Array
(
[price_slot] => 3
[base_price] => 12000
[country] => US
[price_multiplier] => 1.3
[price_value] => 15600
)
[3] => Array
(
[price_slot] => 4
[base_price] => 15000
[country] => US
[price_multiplier] => 1.3
[price_value] => 19500
)
[4] => Array
(
[price_slot] => 5
[base_price] => 4000
[country] => US
[price_multiplier] => 1.3
[price_value] => 5200
)
[5] => Array
(
[price_slot] => 6
[base_price] => 1600
[country] => US
[price_multiplier] => 1.3
[price_value] => 2080
)
Is there any faster way to get around this?
Thanks!
I'm still trying to think of another way, but this is faster:
$result = array_filter($array, function($v) use($priceSlot, $country) {
return ($v['price_slot'] == $priceSlot &&
$v['country'] == $country);
});
Then you would need to access:
echo current($result)['price_value'];
You can get the price_value
in $result
like this:
array_filter($array, function($v) use(&$result, $priceSlot, $country) {
$result = ($v['price_slot'] == $priceSlot &&
$v['country'] == $country) ?
$v['price_value'] : null;
});
A possible solution is by indexing your array (the same thing your database does). By creating an multidimensional array, containing the indexes you're searching on, you'll be able to return the correct entry immediately. You'll definitely see a performance increase when you have to get price value for more than 1 entry (since indexing costs 1 full iteration). Beware that this technique is especially meant for indexing objects, indexing array-values costs more memory.
An example for indexing your array:
$index = array();
foreach ($array as $entry) {
$country = $index['country'];
$priceSl = $index['price_slot'];
if (!isset($index[$country][$pricelSl])) {
$index[$country][$pricelSl] = array();
}
$index[$country][$pricelSl][] = $entry;
}
The next step is to grab the entry from the index:
function getPriceValue($country, $priceSlot) use ($index) {
if (isset($index[$country][$pricelSl])) {
// Return the first entry, we could have more theoretically.
return reset($index[$country][$pricelSl]);
}
return null;
}
TL;DR: 1 full iteration required. Increasing performance when retrieving more than 1 element. Speed of O(1).
Why not create a keyed version of your array at the time you load the data?
foreach ($array as $arrayItem) {
$hash[$arrayItem['price_slot'] . $arrayItem['country']][] = $arrayItem;
}
After that, looking up an entry by price slot and country can be done in constant time:
function getPriceValue($priceSlot, $country) {
return $hash[$priceSlot . $country][0]['price_value'];
}
Of course, this is only useful if you are doing more than one lookup.
NB: The middle array level is only necessary of you want to copy with situations where a given price slot and country does not uniquely define a record.