tags:

views:

1624

answers:

9

I have the following code:

if ($_POST['submit'] == "Next") {
    foreach($_POST['info'] as $key => $value) {
     echo $value;
    }
}

How do I get the foreach function to start from the 2nd key in the array? Thanx.

A: 

in loop:

if ($key == 0) //or whatever
   continue;
Irmantas
I tend to advise against testing for 'special cases' in a loop, if they are known upfront (i.e. the first entry) -> -1
xtofl
@xtol: Why, if I may ask?
nico
+12  A: 
foreach(array_slice($_POST['info'], 1) as $key=>$value) {
    echo $value;
}

Alternatively if you don't want to copy the array you could just do:

$isFirst = true;
foreach($_POST['info'] as $key=>$value) {
    if ($isFirst) {
        $isFirst = false;
        continue;
    }   
    echo $value;
}
Tom Haigh
I think you left an array_slice in the second block by accident
Greg
yeah, removed. thanks
Tom Haigh
I like the isFirst solution better.Its in your face logic, the array slice version could easily be missed when scanning unfamiliar code.
James Anderson
The isFirst solution is also scales better with array size.
Ben Blank
+12  A: 

For reasonably small arrays, use array_slice to create a second one:

foreach(array_slice($_POST['info'],1) as $key=>$value)
{
    echo $value;
}
Michael Stum
This will skip the first 2 keys, but fix that small mistake and it's a good method
Greg
Damn off-by-one errors :-)
Michael Stum
A: 


foreach($_POST['info'] as $key=>$value) {
    if ($key == 0) { //or what ever the first key you're using is
        continue;
    }  else { 
        echo $value;
    }
}

`if` in loop not good, if you can avoid it
bobobobo
+5  A: 

If you were working with a normal array, I'd say to use something like

foreach (array_slice($ome_array, 1) as $k => $v {...

but, since you're looking at a user request, you don't have any real guarantees on the order in which the arguments might be returned - some browser/proxy might change its behavior or you might simply decide to modify your form in the future. Either way, it's in your best interest to ignore the ordering of the array and treat POST values as an unordered hash map, leaving you with two options :

  • copy the array and unset the key you want to ignore
  • loop through the whole array and continue when seeing the key you wish to ignore
Sean McSomething
This is the only answer I've seen so far that even approaches being correct: there is no such thing as "the 2nd key in the array", an associative array is unordered by nature.
George Jempty
From http://www.php.net/types.array : "An array in PHP is actually an ordered map". They act sorta strangely.
Sean McSomething
A: 

if you structure your form differently

  <input type='text' name='quiz[first]' value=""/>
  <input type='text' name='quiz[second]' value=""/>

...then in your PHP

if( isset($_POST['quiz']) AND 
    is_array($_POST['quiz'])) {

    //...and we'll skip $_POST['quiz']['first'] 
    foreach($_POST['quiz'] as $key => $val){
      if($key == "first") continue;
      print $val; 
    }
}

...you can now just loop over that particular structure and access rest normally

How about you use integers instead of strings? (Even though technically it's sent over as a string, it's easier to debug (and generate!) with integers.)
strager
Your `if` in the loop not good
bobobobo
+1  A: 

On a array filled with 1000 elements the difference is quite minimal.

Test:

<?php
function slice($a)
{
    foreach(array_slice($a, 1) as $key)
    {

    }

    return true;
}

function skip($a)
{
    $first = false;

    foreach($a as $key)
    {
     if($first)
     {
      $first = false;
      continue;
     }
    }

    return true;
}

$array = array_fill(0, 1000, 'test');

$t1 = time() + microtime(true);

for ($i = 0; $i < 1000; $i++)
{
    slice($array);
}

var_dump((time() + microtime(true)) - $t1);

echo '<hr />';

$t2 = time() + microtime(true);

for ($i = 0; $i < 1000; $i++)
{
    skip($array);
}

var_dump((time() + microtime(true)) - $t2);
?>

Output:

float(0.23605012893677)

float(0.24102783203125)

alexn
I think it is memory usage that is the more important difference here - maybe measure with memory_get_usage()
Tom Haigh
+2  A: 

If you're willing to throw the first element away, you can use array_shift(). However, this is slow on a huge array. A faster operation would be

reset($a);
unset(key($a));
staticsan
Really? How huge would `array_shift()` become slow for? And why would `unset` be faster?
bobobobo
Ya know, I can't remember why I answered this. Haven't needed this trick in a long time, but I probably got a speedup onceuponatime by doing it the other way! I would imagine an array of some tens of Mb in size might have a difference.
staticsan
ACTUALLY!! `array_shift()` is POISON!! It actually __re-numbers__ all numerical array indices -- even if they are initially sparse (e.g. an array defined `array(1=>'a', 3=>'b', 99=>'c')` would become equivalent to `array('0'=>'b', '1'=c)` after an `array_shift()` operation. Don't `array_shift()` unless this is what you want!!
bobobobo
And so yes, hence why this is faster. The re-indexing operation takes a lot of time.
bobobobo
Well done for doing the research yourself. Just a note that sometimes the keys don't matter.
staticsan
A: 

How about something like this? Read off the first key and value using key() and current(), then array_shift() to dequeue the front element from the array (EDIT: Don't use array_shift(), it renumbers any numerical indices in the array, which you don't always want!).

    <?php

    $arr = array(

      'one' => "ONE!!",
      'two' => "TWO!!",
      'three' => "TREE",
      4 => "Fourth element",
      99 => "We skipped a few here.."

    ) ;

    $firstKey = key( $arr ) ;
    $firstVal = current( $arr ) ;

    echo( "

OK, first values are $firstKey, $firstVal

" ) ; ####array_shift( $arr ) ; #'dequeue' front element # BAD! renumbers! unset( $arr[ $firstKey ] ) ; # BETTER! echo( "

Now for the rest of them

" ) ; foreach( $arr as $key=>$val ) { echo( "

$key => $val

" ) ; } ?>
bobobobo