Skip to content
Advertisement

How do you find the closest value to a number in an associative array?

I have an associative array with 15 different companies and their stock prices, formatted as shown below:

$CloseStockPrice ('Business'=>50.5. 'Business two'=>100.5, .....)

I have found the average stock price:

$Average = (array_sum($CloseStockPrice)/count($CloseStockPrice));

The average ends up being 161.

But I now need to find the closest number (absolute terms) to that average value (161) within the associative array. I need to display the business and the stock value.

My most recent attempt:

function computeClosest(array $CloseStockPrice) 
{
    $closest = 161;
    
    for ($i = 161; $i < count($CloseStockPrice) ; $i++) 
    {
        if ($closest === 161) 
        {
            $closest = $CloseStockPrice[$i];
        } else if ($CloseStockPrice[$i] > 161 && $CloseStockPrice[$i] <= abs($closest)) 
        {
            $closest = $CloseStockPrice[$i];
        } else if ($CloseStockPrice[$i] < 161 && -$CloseStockPrice[$i] < abs($closest)) 
        {
            $closest = $CloseStockPrice[$i];
            return $closest;
        }
    }
}

Any suggestions?

Advertisement

Answer

While you loop through your array of business entries, cache the businesses with prices with the smallest absolute difference involving the average value.

While you might expect a single value in many cases, the fact that multiple qualifying businesses is possible means that you must keep an array of qualifying businesses for most accurate results.

A linear (single loop) process (O(n)) will outperform a sort algorithm (O(n log n)).
https://stackoverflow.com/q/56506410/2943403

Code: (Demo)

$closeStockPrice = [
    'A' => 50,
    'B' => 155,
    'C' => 75,
    'D' => 245,
    'E' => 300,
    'F' => 100,
    'G' => 153,
];

$average = array_sum($closeStockPrice) / count($closeStockPrice);

$bestDistances = [];
foreach ($closeStockPrice as $business => $price) {
    $distance = abs($average - $price);
    $current = current($bestDistances);
    if (!$bestDistances || $current > $distance) {
        $bestDistances = [$business => $distance];  // new best distance
    } elseif ($current === $distance) {
        $bestDistances[$business] = $distance;  // push business with same distance
    }
}
var_export([
    'average' => $average,
    'bestDistances' => $bestDistances,
    'bestBusinessPrices' => array_intersect_key($closeStockPrice, $bestDistances)
]);

Output:

array (
  'average' => 154,
  'bestDistances' => 
  array (
    'B' => 1,
    'G' => 1,
  ),
  'bestBusinessPrices' => 
  array (
    'B' => 155,
    'G' => 153,
  ),
)
User contributions licensed under: CC BY-SA
7 People found this is helpful
Advertisement