2

is there a simple way to access the nth element in a multidimensional array in php?

so for example

$arr = array( 
[0] => array(1,4,7,3,53),
[6] => array(6,3,9,12,51,7),
[2] => array(9,94,54,3,87));

the 12th element would be 9.

array keys are not necessarily in order, nor each array row is of the same length.

Ray S.
  • 1,192
  • 3
  • 15
  • 27
  • Nope. You would have to code this manually. – Jon Sep 17 '13 at 20:35
  • Well, it's not the 12th element, it's the element in index X of array in index Y. You'd have to flatten into a single array or do some logic. What have you tried so far? – elclanrs Sep 17 '13 at 20:35
  • flatenning is difficult in my situation – Ray S. Sep 17 '13 at 20:36
  • 1
    @RayS: http://stackoverflow.com/questions/1319903/how-to-flatten-a-multidimensional-array – Steven Liao Sep 17 '13 at 20:37
  • 2
    Why not? `call_user_func_array('array_merge', $array)[12]`. Done. – elclanrs Sep 17 '13 at 20:37
  • @elclanrs: You mean `[11]` ^~^ (P.S. your syntax only works in PHP 5.4+). – gen_Eric Sep 17 '13 at 20:39
  • 1
    @elclanrs it's `call_user_func_array('array_merge', $array)[11]`:) – Charaf JRA Sep 17 '13 at 20:39
  • 2
    Flattening is going to do a possibly large amount of work (and then throw it away) for really dubious benefit. If the aim is to have an one-liner just put the code inside a function. – Jon Sep 17 '13 at 20:39
  • @Jon, I agree, there are options that perform better, but no code, no help... – elclanrs Sep 17 '13 at 20:41
  • @Jon: Performance requirements aside (in this case I would argue performance concerns are premature), flattening makes the code more intuitive and easy to read. Flattening the array and grabbing the 12th element is what you are doing logically in your head. – Steven Liao Sep 17 '13 at 20:44
  • @StevenLiao: If you believe that `call_user_func_array('array_merge', $array)` is intuitive and easy to read then we will have to disagree. If clear code is the aim, I would create a `FlattenedArrayAccess implements ArrayAccess` class and do `$f = new FlattenedArrayAccess($array); echo $f[11];`. – Jon Sep 17 '13 at 20:50
  • @StevenLiao: Also, on what exactly do you base the assertion that performance concerns are premature? When talking about a generic-use (library) function, and IMHO this case is dangerously close to one, performance is *always* a concern because you don't know who is going to use it and in what way. – Jon Sep 17 '13 at 20:52
  • @Jon: I argue that [this function](http://stackoverflow.com/a/1320156/1596731) (as I linked to above) would make it clear, whether wrapped in a class or not. We can always rewrite if there is a need. – Steven Liao Sep 17 '13 at 20:54
  • @Jon: I think that's one of the points he's making, you can always build a new implementation if performance issue arise, and it's a trivial change. It also depends on how you reason about your logic. I agree with StevenLiao, that's how I'd initially think about this particular problem. – elclanrs Sep 17 '13 at 20:55
  • @StevenLiao: So you agree that we would need a custom function. In which case, why should that function actually create a flattened array? We don't need one, we just want to access based on a virtual flattened index. Why do the work needlessly? – Jon Sep 17 '13 at 20:58
  • @elclanrs: You should go one level deeper when thinking about this. The aim is to index into the array *as if* it were flattened, so a hypothetical `FlattenedArrayAccess` is an abstraction that hides the implementation and allows us to swap it out for a better one later on. Flattening the array "in your face" is a concrete implementation (it returns an array!) that actually *limits* your options going forward because of BC breaks (in this case, it *kills* your options short of introducing a whole new function). – Jon Sep 17 '13 at 21:01
  • @Jon: I understand your point. How about an flatten generator? That would be IMO the compromise between readability ("flatten this then take that") and performance, given that PHP is not a lazy language but generators don't create a whole intermediate object. It's only PHP 5.5+ but that's what I would do if I were to implement this today optimized for performance. – elclanrs Sep 17 '13 at 21:09
  • @elclanrs: A flatten generator would be very useful in general but not the best choice here because it would likely be orders of magnitude slower; again, why pay for something you don't need? We are not interested in all those items (at least that's how I read the question). – Jon Sep 17 '13 at 21:13

3 Answers3

-1

untested, should work...

$arr = array( 
0 => array(1,4,7,3,53),  // your code was wrong here
6 => array(6,3,9,12,51,7),
2 => array(9,94,54,3,87));

function getnth ($array, $offset) {
    $tmp_arr = array();
    foreach ($array as $key => $value) {
        foreach ($value as $val) {
        $tmp_arr[] = $val;
        }
    }
    return (isset($tmp_arr[$offset -1]) ? $tmp_arr[$offset -1] : FALSE);
}

getnth($arr, 12);

Edit: got to admit, the array_merge version is better....

Edit2: this is probably faster, if performance is an issue....

function getnth($array, $offset) {
    $i = 0;
    foreach ($array as $key => $value){
        $size = count($value);
        $i += $size;
        if($offset <= $i) {
            $new_off = $size - ($i - $offset) -1 ;
            return $value[$new_off];
        }
    }
    return FALSE;
}
joschua011
  • 4,157
  • 4
  • 20
  • 25
-1

Try this :

<?php
    $arr = array( 
     '0'=> array(1,4,7,3,53),
     '6'=>array(6,3,9,12,51,7),
     '2'=>array(9,94,54,3,87)
    );
    $newArray=array();
    foreach($arr as $array){

    $newArray=array_merge($newArray, $array);
    }
    echo $newArray[11];
?>
Charaf JRA
  • 8,249
  • 1
  • 34
  • 44
-4
function get_item($arr, $path, $delim = '.') {
    $path = explode($delim, $path);
    $result = $arr;
    foreach ($path as $item) {
        if (isset($result[$item])) {
            $result = $result[$item];
        } else {
            return null;
        }
    }
    return $result;
}

using:

echo get_item($arr, 'item.value.3.4.2.etc');
user2058005
  • 125
  • 2
  • 10