Fin the max value in array lower than x

Array = 1,5,2,3,7,1,2,4,8,4,0,9,11,15
x = 8
z = ?
How to find the max value that is lower than x, in my example it is 7 ( z )…

Couldn’t you sort the array so it is in numerical order, then find the number 8, and then choose the index right before that one? Since it is sorted numerically it should be the maximum.

2 Likes

After a numeric sort I think array_search would work well here.

Though IMHO if you’re going to do a “key - 1” it would be a good idea to use array_key_exists in case x is the lowest value.

You wouldn’t have to use array_key_exists, as if it is the very first value, it will have a key of 0 (assuming it isn’t using an associative array). Associative arrays don’t matter either, as when you sort (see the first note), it assigns a new key that starts at 0.

<?php
$numbers=array(1,5,2,3,7,1,2,4,8,4,0,9,11,15);
$sort = sort($numbers);
$arrlength=count($numbers);
for($x=0;$x<$arrlength;$x++)
{
    echo $numbers[$x]. "\n";
}
$value = 8;
$key = array_search($value, $sort);
$keys = $key-1;
echo "max ",$key ."\n";
echo "avr ",$sort[$keys] ."\n";
?>

I made this script but it gives to me an error

Warning: array_search() expects parameter 2 to be array, boolean given

How to sort the array and use it as variable ?

Sort returns a bool. You want to use array_search($value, $numbers); instead.

And change $sort[$keys] to $numbers[$keys]

Also, I would change

$keys = $key-1;

to

$keys = ($key != 0) ? $key-1 : $key;

That way, if array_search returns the very first value in the array, it doesn’t blow up.

1 Like

Yes sort returns a boolean

Return Values
Returns TRUE on success or FALSE on failure.

So unless you want to test for its success or failure for some reason once you do

sort($array)

$array will be sorted

EDIT
ninja’d :smile:

1 Like

i need to use sorted array not the normal , in line 2 i tried o sort the array

Correct, sort($numbers) is updating the $numbers array to be sorted. It isn’t providing a new array, it is replacing itself.

Your for-loop should represent that, as the output should have been sequential

No need to sort. This is a job for array_reduce:

<?php
$numbers=array(1,5,2,3,7,1,2,4,8,4,0,9,11,15);
$x = 8;
$z = array_reduce($numbers,function($max,$number) use($x) {

    // Ignore if greater
    if ($number >= $x) return $max;

    // First one less than x
    if ($max === null)  return $number;

    // Replace if greater
    return $max < $number ? $number : $max;

},null);
echo $z . "\n";
2 Likes

@ahundiak good job man that does the work also thanks to all other who replied. All the best

Just be sure that you can actually explain to your instructor what array_reduce does. Otherwise, it might be a bit embarrassing.

1 Like

Looking at all these fancy codes I am wondering why a simple three-liner with a loop and a condition can’t do.

About a year ago I started to dabble in functional programming. So now whenever I get the urge to foreach over something, I try to see if one of the builtin array functions could be used instead. It’s what all the hip developers are doing.

I do think you need more than one comparison for maintainability. I’m sure I could combine the three statements into one but it would be messy. Unless you have a trick up your sleeve?

but you don’t need a function here. You need just a simple value out of array.

Regarding the number of conditions, I think that your second one is superfluous while to make something like (condition && condition) from the rest doesn’t look that scaring to me.

I guess there’s always more than one way to do something.

This works, but I can’t say I feel all that good about it. Feels hacky.

$test_value = 8;
$test_array = [1,3,5,7,9,2,4,6,8];
function keep_less_thans(&$array_item, $array_key, $test_value){
  if ($array_item >= $test_value){
    $array_item = NULL;
  }
}
array_walk($test_array, 'keep_less_thans', $test_value);
rsort($test_array);
print_r($test_array[0]);

This is how I would handle it:

$newNumbers=$numbers=array(1,5,2,3,7,1,2,4,8,4,0,9,11,15);// protect the original array by copying it
sort($newNumbers); // orders the array
$value = 8;
$key = array_search($value, $newNumbers); //searches  for the upper limit
echo "max ",$newNumbers[($key>0) ?   $key-1 : 0 ] ."\n";// return the key prior to the upper limit 

Admittedly, this will error out if the exact limit is not present. For example if there is no 8 in the array.

1 Like

@Mittineague

array_filter could get rid of your keep_less_thans function:

$test_value = 8;
$test_array = [1,3,5,7,9,2,4,6,8];
$lessThans = array_filter($test_array,function($value)  use($test_value) {
    return $value < $test_value;
});
rsort($lessThans);
3 Likes

It is not a matter of many ways, it’s a matter of sanity. I’ve seen many times the PHP users’ enigmatic inclination to writing the longest and most entangled code they can muster.

Ok, a version from @ahundiak is good for educational purpose, but I’d hate if I had a colleague writing like this. May be it’s only me, but my job involves not only writing but also reading considerable amounts of code. And when I am reading the code, I want to be able to comprehend it’s purpose, but if it takes a couple lookups to PHP manual, it distracts me from the current task.

To me, a simple loop like this

$src = array(1,5,2,3,7,1,2,4,8,4,0,9,11,15);
$max = 8;
$res = null;
foreach ($src as $num) {
    if ($num > $res && $num < $max) {
        $res = $num;
    }
}

is incomparable to any “other way to do it” presented here, as it’s both simpler and way more readable. It’s a code that even almost literally reads as the task description, if you read it aloud

for each array element, if it’s bigger than current value and at the same time it’s less than max value, then assign it to current value.

Try to read aloud one of any other codes here :slight_smile:

not to mention that unlike other suggestions it involves only one single loop over the source array. Not I am going to say that it has any effect on performance but still…

2 Likes