0

Imagine some arrays set up in a PHP script something like this:

 $foo = array(
     'bob'=>976,
     'Jack'=>'Octopus',
     'bar'=>'baz',
     'pi'=>'irrational',
     'other'=>123
 );
 
 $biz = array(
     'Harry'=>'Dogs',
     'Zim'=>'zoom',
     'bar'=>'baz',
 );

Now lets say (for reasons) I want to get the content of the array one index before "bar". Like this:

 function get_before($ar,$what){
     // ... the bit I'm still working on
 }
 
 echo get_before($foo,'bar'); // should be Octopus
 echo get_before($biz,'bar'); // should be zoom

I figure that what I want is the key that comes before mine. Is there a way to get that? (You can assume that the arrays will rarely be as big as 50 elements).

I've been toying with using array_keys, doing a search on the new array, getting the index value of the result minus one to find the new key, then using that key to get my target. It just seems needless intensive and hackish - a simpler approach would make me happier as the function I create will get called a lot every page load.

  • search bar for the array index with the name you provided (e.g. 'bar'),then do a (minus 1) array index data retrieval. – Ken Lee Dec 24 '20 at 23:24
  • 1
    Why are you using an associative array if order is important? – Barmar Dec 24 '20 at 23:30
  • I don't think there's anything significantly better than what you describe in the last paragraph. There's nothing built-in to do this. – Barmar Dec 24 '20 at 23:38

4 Answers4

2

You can use array_search to find the index of the key. And using the index -1 find the previous kay=>value

       $array = array(
             'bob'=>976,
             'Jack'=>'Octopus',
             'bar'=>'baz',
             'pi'=>'irrational',
             'other'=>123
         );

function find_previous($array, $needle) {
    $keys  = array_keys($array);
    $index = array_search($needle, $keys);

    return $index ? $array[$keys[$index - 1]] : false;
}
var_dump(find_previous($array,'bar'));
Stefan Avramovic
  • 1,365
  • 2
  • 11
  • 20
1

I don't know what is the usage of this but something simple must do the work.

function getPreviousValue($array, $key) {
    if (isset($array[$key])) { // checking if the passed key is existing
        end($array); // set internal array pointer to the end of the array
        while (key($array) !== $key) { // looping through the array to set the internal pointer position to the passed key
            prev($array);
        }
        
        prev($array); // set the internal position to previous key
        
        return current($array); // return the current value
    }
    
    return null;
}
GTsvetanov
  • 1,250
  • 6
  • 16
  • I don't think it makes a difference, but why do you start at the end rather than the beginning? – Barmar Dec 24 '20 at 23:37
  • 1
    @Barmar because of semantic and better readability. You want previous value so for me its better if you use only prev() instead of next() and then prev() – GTsvetanov Dec 24 '20 at 23:41
1

You can loop through your array, and store the last value and wait until you have a matching key:

<?php

$foo = array(
    'bob'   => 976,
    'Jack'  => 'Octopus',
    'bar'   => 'baz',
    'pi'    => 'irrational',
    'other' => 123
);


function get_value_before_given_key($array, $needle) {
    $last = $result = null;
    foreach($array as $key => $value) {
        if($needle === $key) {
            $result = $last;
            break;
        }
        $last = $value;
    }

    return $result;
}

var_dump(get_value_before_given_key($foo, 'pi'));
var_dump(get_value_before_given_key($foo, 'nokey'));

Output:

string(3) "baz"
NULL
Progrock
  • 7,373
  • 1
  • 19
  • 25
1

Assuming that...

  1. You only want to output the key of the previous array item
  2. You want to return FALSE if the key isn't found
  3. You want to return TRUE if the key was the first in the array
    • To distinguish from FALSE where key is present in array

Subject array

$array = [
    'bob'   => 976,
    'Jack'  => 'Octopus',
    'bar'   => 'baz',
    'pi'    => 'irrational',
    'other' => 123
];

Using foreach

function get_previous_a($array, $needle)
{
    $last = TRUE;
    foreach($array as $key => $value) {
        if($needle === $key)
            return $last;
        else
            $last = $key;
    }
    return FALSE;
}


var_dump(
    get_previous_a($array, "pi"),
    get_previous_a($array, "other"),
    get_previous_a($array, "bob"),
    get_previous_a($array, 132145) 
);

/* Output:

string(3) "bar"
string(2) "pi"
TRUE
bool(false)

*/    

Using array_*

function get_previous_b($array, $needle)
{
    $keys       = array_keys($array);
    $curr_index = array_search($needle, $keys);
    $key        = ( $curr_index > 0 ) ? $keys[$curr_index - 1] : TRUE;
    return ( $curr_index === FALSE ) ? FALSE : $key;
}

var_dump(
    get_previous_b($array, "pi"),
    get_previous_b($array, "other"),
    get_previous_b($array, "bob"),
    get_previous_b($array, 132145) 
);

/* Output:

string(3) "bar"
string(2) "pi"
TRUE
bool(false)

*/
Steven
  • 6,053
  • 2
  • 16
  • 28