Martin
Martin

Reputation: 473

Get the highest key in array less than 'x'

How do I get the highest key from an array where the key is less than a given number?

$arr = array('10' => 'a', '20' => 'b', '30' => 'c', '40' => 'd', '50' => 'e');
$max = max(array_keys($arr));

Which will set $max to '50'. But if I want to get the max key where the key is less than '38', is there a way to avoid going through a loop?

Upvotes: 1

Views: 1496

Answers (5)

Syscall
Syscall

Reputation: 19764

You can use array_filter() to get the array with keys less than 38, and the use max().

PHP 7.4+

$arr = ['10' => 'a', '20' => 'b', '30' => 'c', '40' => 'd', '50' => 'e'];
$threshold = 38;

// Keep elements under condition:
$limit = array_filter($arr, fn($key) => $key < $threshold,  ARRAY_FILTER_USE_KEY);

$max = max(array_keys($limit)); // get the max of remain keys.
var_dump($max);

Outputs:

int(30)

Before PHP 7.4

$threshold = 38;
$arr = ['10' => 'a', '20' => 'b', '30' => 'c', '40' => 'd', '50' => 'e'];

$filtered = array_filter($arr, function($key) use ($threshold) { return $key < $threshold; },  ARRAY_FILTER_USE_KEY);
$max = max(array_keys($filtered));
var_dump($max); // int(30)

Upvotes: 3

Sherif
Sherif

Reputation: 11942

Since you have both a greather-than AND less-than requirement, max doesn't satisfy your requirements by itself. You'll need both conditions checked as you traverse the array. You can't avoid a loop, in the sense that you must traverse the array to find the value, but you can bail early once both conditions are satisfied. So your worst case complexity here is O(n).

function getKeyRange(array $array, $min, $max = 0) {

    foreach ($array as $key => $value) {

        if ($key > $max && $key < $min) {
            $max = $key;
        }

        if ($key >= $min) {
            return $max;
        }
    }

}

echo getKeyRange([10 => 'a', 20 => 'b', 30 => 'c', 40 => 'd', 50 => 'e'], 38); // 30

Upvotes: 0

AbraCadaver
AbraCadaver

Reputation: 79024

Pretty easy with a loop since you know where to start:

for($key = 38, $max = 0; !$max; $key--, $max = $arr[$key] ?? 0);

Upvotes: 1

BadHorsie
BadHorsie

Reputation: 14564

function getMaxKey($array, $max) {
    $filtered = array_filter(array_keys($array), function($key) use ($max) {
        return $key < $max;
    });
    return max(array_keys($filtered));
}

// Usage
$max = getMaxKey($arr, 38);

Upvotes: -1

treyBake
treyBake

Reputation: 6568

You can use array_filter() to essentially do your (for/foreach/while)loop logic for you:

<?php
    $data = array('10' => 'a', '20' => 'b', '30' => 'c', '40' => 'd', '50' => 'e');
    # get the keys as an array
    $keys = array_keys($data);
    # define your criteria
    $max = 38;

    # use array_filter to return elements lower than $max
    $belowMax = array_filter(
        $keys, 
        function($num) use ($max)
        {
            return $num < $max;
        } 
    );

    # use max() to get highest value
    $highest = max($belowMax);

    # print highest key under $max
    echo '<pre>'. print_r($highest, 1). '</pre>';

See fiddle

Upvotes: 3

Related Questions