3

I need to find both negative and positive values closest to zero in an array.

  • If the array is empty we return 0.
  • If the array has for example -7, 7 we return 7.

Is this the proper way to do it?

$ts = [1.7, 7, -10, 13, 8.4, -7.2, -12, -3.7, 3.5, -9.6, 6.5, -1.7, -6.2, 7];

function closestToZero (array $ts)
{
    if(empty($ts)){

        return 0;
    }

    $negativeArr = [];
    $postiveValue = [];

    foreach ($ts as $number) {
        if ($number < 0) {
            $negativeArr[] = $number;
        }elseif ($number > 0 ) {

            $postiveValue[] = $number;
        }
    }

    if(!empty($negativeArr)){

        $minnegative = max($negativeArr);
    }

    if (!empty($postiveValue)) {
        $minPositive = min($postiveValue);
    }
    if ((abs($minnegative) - $minPositive) == 0) {

        return $minPositive;
    }else{
        return $minnegative.' '.$minPositive;
    }



}

echo "Result is ".closestToZero($ts);

EDIT:

i was actually looking for an optimized way to do it, after some researches i end up with this witch is more optimized

    //if the array is empty we do nothing we return
if(empty($ts)){

    return 0;
}else{

    $referenceValue = 0;

    //the trick is to add the reference value to the array if it doesnt exist
    if (in_array($referenceValue, $ts) === FALSE) {
        array_push($ts, $referenceValue);
    }

    //we sort the array in an ascending order
    sort($ts);

    // now we are able to get the nearest postive and negative values from 0
    $referenceValueKey = array_search($referenceValue, $ts);

    $positiveValueKey = $referenceValueKey + 1;
    $negativeValueKey = $referenceValueKey - 1;

    $result = '';
    // if there is the same number as negative and positive in the array, we return the positive one
    if((abs($ts[$negativeValueKey]) - $ts[$positiveValueKey]) == 0 )
    {
        $result.= $ts[$positiveValueKey];

    }else{

        $result.= $ts[$negativeValueKey].' '.$ts[$positiveValueKey];
    }

    return $result;



}






}
  • Possible duplicate of [Nearest value from an array](https://stackoverflow.com/questions/5464919/nearest-value-from-an-array) – Patrick Q Jul 20 '18 at 14:47
  • I don't think you need to be asking. If it works, then it is a proper way to do it. If you want it to be optimized, that's a different question. – Howard P Jul 20 '18 at 14:48
  • 2
    Might be a better fit for https://codereview.stackexchange.com/ – CD001 Jul 20 '18 at 14:49

3 Answers3

2

You can do this in a lot less code:

<?php

function getClosest(array $x)
{
    // put them in order first
    sort($x);

    $results = [];

    foreach($x as $y) {
        if ($y < 0) {
            $results['-'] = $y; // next negative is closer to 0
        } else {
            $results['+'] = $y; // first positive is closest to 0
            return $results;
        }
    }
    return count($results) > 0 ? $results : 0;
}

$x = [1.7, 7, -10, 13, 8.4, -7.2, -12, -3.7, 3.5, -9.6, 6.5, -1.7, -6.2, 7];

$y = getClosest($x);
var_dump($y);

Which returns:

array(2) { ["-"]=> float(-1.7) ["+"]=> float(1.7) }
delboy1978uk
  • 12,118
  • 2
  • 21
  • 39
  • it works like a charrm , but it doesnt solve the probleme completly since we are expecting numbers as retunrned values like this : echo "Result is ". getClosest($x); also it should handle the case of an empty array at the begining –  Jul 21 '18 at 15:42
  • regarding the empty array, it'll skip the loop and return 0 at the end, putting extra ifs at the beginning is a micro optimisation imo. As for what is returned, should the negative and positive be compared, and only the closest returned? What if (like the example) they are both the same apart from polarity? which number should be returned? – delboy1978uk Jul 23 '18 at 11:16
0

Took me a while but I solved it. This function not only finds the nearest positive to 0, but also takes any other point in calculation.

def closest_positive_to_zero(list_of_temperatures, needed_point):
    print(f"got: {list_of_temperatures}") #[7, -10, 4, -7.2, 1.7, -1.7, -6.2, 1.7, 1.8, 1.7, 10]
    sorted_list = sorted(set(list_of_temperatures), key=lambda temperature: abs(temperature-needed_point))  # used a set to get rid of dublicates, sorted with lambda closest to 0
    print(f"sorted: {sorted_list}") #[1.7, -1.7, 1.8, 4, -6.2, 7, -7.2, 10, -10]
    return sorted_list[1] if sorted_list[0] < sorted_list[1] and abs(sorted_list[0]) == abs(sorted_list[1]) else sorted_list[0] # if there are two first same closest numbers (+1.7 and -1.7) take the positive one

list_of_temperatures = [7, -10, 4, -7.2, 1.7, -1.7, -6.2, 1.7, 1.8, 1.7, 10]
the_closest = closest_positive_to_zero(list_of_temperatures, 0)
print(f"{the_closest}")
-2
<?php
$array = [-5, 2, -4, 3, 7];
$positive = array_filter($array, function ($v) {
  return $v > 0;
});
$negative = array_filter($array, function ($v) {
  return $v < 0;
});
print_r(['positive' => array_values($positive)[0], 'negative' => end($negative)]);
TsV
  • 629
  • 4
  • 7
  • Where is the sorting? Maybe with sorting it would work. Try with `$array = [-5, 2.1, 1.9, -4, 3, 7];` and will give `[positive] => 2.1` which is wrong. – qräbnö Jul 20 '18 at 15:14