Skip to content
Advertisement

Get closest smaller array key of a multidimensional array

I´ve an array $curvepoint which is structured like that:

Array
(
    [0] => Array
        (
            [ID] => 57587
            [Pos0] => 1
        )
    [1] => Array
        (
            [ID] => 57588
            [Pos0] => 2
        )

    [2] => Array
        (
            [ID] => 57589
            [Pos0] => 22
        )

    [3] => Array
        (
            [ID] => 57590
            [Pos0] => 39
        )
)

Now I want to get the closest smaller array key in relation to the value [Pos0] and a given number.

Example:

If I have the variable $number = 20 the loop should return 1, because the closest smaller [Pos0] value of 20 would be [Pos0] => 2 which is stored in the array key 1.

I´m very unsure how to get the results. I´ve tried to use a combination of array_slice and array_intersect inside a foreach loop.

Original try:

$number = 20 

foreach ($curvepoint as $test) {

    $two_nearest = array_slice(array_intersect(array_keys($test['Pos0']),range(0,$number)), -2);
    $less_near = $test['Pos0'][$two_nearest[0]];

    echo $less_near;
}

Edited code:

$value = 10;

function findClosestLowerPosition(array $curvepoint , int $value): ?int
{
    $lowerPositions = array_filter(
        array_column($curvepoint , 'Pos0'),
        function ($a) use ($value) {
            return $a < $value;
        }
    );
    if (empty($lowerPositions)) {
        return null;
    }

}

print_r($lowerPositions);

Advertisement

Answer

Proposed solution:

/**
 * Searches for the index of an element that has the closest of all
 * the lower values than the specified one.
 *
 * @return int|null Numeric position of the closest lower element if found,
 * NULL otherwise
 */
function findClosestLowerPosition(array $curvepoints, int $value): ?int
{
    $lowerPositions = array_filter(
        array_column($curvepoints, 'Pos0'),
        function ($a) use ($value) {
            return $a < $value;
        }
    );
    if (empty($lowerPositions)) {
        return null;
    }

    rsort($lowerPositions);
    $closestPosition = $lowerPositions[0];
    foreach ($curvepoints as $key => $curvepoint) {
        if ($curvepoint['Pos0'] === $closestPosition) {
            return $key;
        }
    }
}

How it works:

  • First step gets the values of all the lower positions. This is achieved by first extracting every Pos0 value through array_column. The result of that function is a simple numeric array which is then passed as an argument to array_filter, which only filters the values lower than the specified one.
  • After that we check if there are any lower values at all – if none are found, our filtered array will be empty. In that case, we return null to indicate such a value doesn’t exist.
  • Once we have the lower values, we sort them in reverse order (greater to lower), in order to place the closest value in the first position of the array, then we get it by accessing the first index (which is always 0 for PHP auto-generated arrays).
  • Ultimately, we iterate our original array to locate the element whose value matches the closest one. As soon as a match is found, we return the key of that element.

Note that this whole algorithm assumes there can be no duplicate values of Pos0. If your elements can have the same position value, then you need to determine rules how to break the ties.

User contributions licensed under: CC BY-SA
2 People found this is helpful
Advertisement