18

How get you get element key and value of an at the n position array at a particular position without loop.

Imagine

$postion = 3; // get array at 3rd position
$array = array(
        "A" => "Four",
        "B" => "twp",
        "C" => "three",
        "D" => "Four",
        "E" => "Five",
        "F" => "Four");


$keys = array_keys($array);
$value = array_values($array);

echo implode(array_slice($keys, $postion, 1)), PHP_EOL; // Key at 3rd posstion
echo implode(array_slice($value, $postion, 1)), PHP_EOL; // Value at n position

Output

D
Four

Issues With the method is

  • Multiple Duplication of the array resulting higher memory usage

Why not use loop

  • You have to get multiple position multiple times .. looping large data set not efficient either

Why not use a Database

  • Yes working with memory based database like Redis can make life easier but am particular array optimisation

Why not use SplFixedArray

  • This would have been solution but i the follow weer because am not using positive keys ( I really this is nor fair on php part)

    Fatal error: Uncaught exception 'InvalidArgumentException' 
    with message 'array must contain only positive integer keys' 
    

What do you mean by large data set :

  • Actually i stumble on this issue when trying to as this question Managing mega Arrays in PHP so am looking at 1e6 or 1e7 with 512M memory limit

Am sure something like fseek for array would do the trick .. but not sure if that exists

Community
  • 1
  • 1
Baba
  • 94,024
  • 28
  • 166
  • 217

4 Answers4

17

Assuming PHP 5.4, with array dereferencing:

echo $array[array_keys($array)[$position]];

In earlier versions you need to break it into two lines:

$keys = array_keys($array);
echo $array[$keys[$position]];

It would also be worth using the two-line approach in 5.4+ if you have to access multiple elements, to allow you to only call the relatively expensive array_keys() function once. Also the dereferencing approach assumes that the specific position within the array exists, which it may not. Breaking it into multiple operations would allow you to handle that error case.

Although of course you don't ever need access to the key, you can simply do:

echo array_values($array)[$position];
// or
$values = array_values($array);
echo $values[$position];

Edit

The ArrayIterator class can also do this for you:

$iterator = new ArrayIterator($array);
$iterator->seek($position);

echo $iterator->key(), " = ", $iterator->current(); // D = Four

This is probably the least expensive way to do this assuming it doesn't create a copy of the array in memory when you do it (still researching this element), and likely the best method for multiple accesses of arbitrary keys.

Baba
  • 94,024
  • 28
  • 166
  • 217
DaveRandom
  • 87,921
  • 11
  • 154
  • 174
  • 2
    The OP's problem, I suppose, is that `array_keys` in his case is too expensive - when an array contains millions of items, for example. Then again, I don't quite get the use case of all this: you rarely have to work with zounds of items in the code instead of DB. – raina77ow Feb 26 '13 at 16:22
  • @raina77ow updated to use `ArrayIterator`, but I'm not sure whether that would just create a copy underneath anyway, in which case you've lost any improvement that would afford. – DaveRandom Feb 26 '13 at 16:37
  • @DaveRandom i still think you cheated ... even `ArrayObject` does not have seek .... nice one – Baba May 25 '13 at 09:46
6

What you want is not possible. PHP's arrays have efficient access by key, but don't have efficient access by offset. The order is only available as a linked list, so the best efficiency you can hope for is an O(n) loop, which just goes through the array and looks for the offset:

$i = 0;
foreach ($array as $value) {
    if ($i++ === $offset) {
        // found value
    }
}

If you want this operation to be fast, then you'll have to use a proper, numerically and sequentially indexed array.

NikiC
  • 100,734
  • 37
  • 191
  • 225
  • @DaveRandom Erm... what about http://stackoverflow.com/a/10058358/1229023 (and its first comment)? – raina77ow Feb 26 '13 at 16:53
  • @raina77ow more evidence http://stackoverflow.com/questions/14848910/unexpected-behaviour-of-current-in-a-foreach-loop – Baba Feb 26 '13 at 17:22
  • 2
    @raina77ow I have to be honest, I'm more inclined to go with the [PHP core dev guy](https://github.com/php/php-src/commits?author=nikic) who [has `foreach` related commits in the core](https://github.com/php/php-src/commit/de80e3ce4b5b7a9ec0cfdd0778e77027a7ebfcc2) ;-) – DaveRandom Feb 27 '13 at 14:13
  • @DaveRandom I see. I admit, though, that I still can't see how in this particular case `foreach` can be less performant: shouldn't the rule for `refcount === 1 => no copying` be applied to `$array` here? – raina77ow Feb 27 '13 at 15:10
3

in fact you don't need the $values array:

$keys = array_keys($array);

$value_3=$array[$keys[3]];
Naryl
  • 1,878
  • 1
  • 10
  • 12
0

I dont understand your question well but if you need a key and element from position

$position = 3; // get array at 3rd position
$array = array(
        "A" => "Four",
        "B" => "twp",
        "C" => "three",
        "D" => "Four",
        "E" => "Five",
        "F" => "Four");


$keys = array_keys($array);
$values = array_values($array);

if($values[$position] == "Four" && $keys[$position] == "D") {
    echo "All it's Right!\n";
}

you dont need implode for that task

rkmax
  • 17,633
  • 23
  • 91
  • 176