Current location: Hot Scripts Forums » Programming Languages » PHP » Iterating Associative arrays with foreach


Iterating Associative arrays with foreach

Reply
  #1 (permalink)  
Old 11-08-07, 02:00 PM
divya divya is offline
Newbie Coder
 
Join Date: Nov 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Iterating Associative arrays with foreach

I am a new PHP programmer.

I am trying to iterate an associative array with a foreach loop using :
i) key value pair line 4-7
ii) only the value line 11-16
The Code, Output and Problem is as follows:

*Code
=====
PHP Code:

$testArray =  array("first"=>"Mon","second"=>"Tuesday","third"=>"Wednesday","fourth"=>"Thrusday");
 
print_r($testArray);
    echo 
"<p><strong>Iterating with key,value </strong></p>";
     foreach(
$testArray as $key=>$value)
    {
          echo 
"<p>Key: "$key" is $value </p>";
    }
   
//$NotUsed = $testArray;
   //reset($testArray);  
  
echo "<p><strong>Iterating with value </strong></p>";
 foreach(
$testArray as $test)
 {
      echo 
"<p>Key: "key($testArray)," Current value: ",current($testArray),"</p>";
     echo 
"<p>Value: $test</p>";
     
next($testArray);

*Output
======
Array ( [first] => Mon [second] => Tuesday [third] => Wednesday [fourth] => Thrusday )

Iterating with key,value

Key: first is Mon

Key: second is Tuesday

Key: third is Wednesday

Key: fourth is Thrusday

Iterating with value

Key: second Current value: Tuesday

Value: Mon

Key: third Current value: Wednesday

Value: Tuesday

Key: fourth Current value: Thrusday

Value: Wednesday

Key: Current value:

Value: Thrusday


*Problem
======

I am not able to iterate the keys of the associative array correctly in the second foreach loop.
The code somehow works if I enable the assignment at line 8. $NotUsed = $testArray;

Can someone help me with this weird problem?

Thanks,
Divya

Last edited by Nico; 11-08-07 at 02:11 PM.
Reply With Quote
  #2 (permalink)  
Old 11-08-07, 07:08 PM
phpdoctor's Avatar
phpdoctor phpdoctor is offline
Code Guru
 
Join Date: Feb 2007
Location: New Zealand
Posts: 767
Thanks: 4
Thanked 2 Times in 2 Posts
Is your echo statements your using "," instead of "."? Didnt know you could use them.....

Anyway in your second loop your using key, current and next functions..... Mind showing us the code?

Im quiet sure what your asking...

Lex
__________________
01010000 01001000 01010000
Reply With Quote
  #3 (permalink)  
Old 11-08-07, 08:24 PM
Jay6390's Avatar
Jay6390 Jay6390 is offline
Code Master
 
Join Date: Apr 2007
Location: United Kingdom
Posts: 1,330
Thanks: 0
Thanked 0 Times in 0 Posts
Whilst i dont understand why it is that you are getting this strange output, i cant help but wonder why it is that you cant use the foreach($data as $key=>$value) system. as you have shown in the example, that works. why would you need to use that system?

Jay
__________________
Useful Tutorials
[ PHP Video-1-2-3 ] [ MySQL 1-2-3 ]
For any php function reference type

www.php.net/FunctionName
Reply With Quote
  #4 (permalink)  
Old 11-09-07, 10:37 AM
divya divya is offline
Newbie Coder
 
Join Date: Nov 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
echo statements can use both "," and "."

key, current and next functions are inbuilt PHP functions for iterating an array

key(array) - Returns key of the current array element
current(array) - Returns the current array element
next(array)- Moves the internal array pointer to the next element
Reply With Quote
  #5 (permalink)  
Old 11-09-07, 10:39 AM
divya divya is offline
Newbie Coder
 
Join Date: Nov 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Yes the first foreach loop is the traditional way to iterate through the array.

I just happened to use the second foreach loop and was trying to access the corresponding keys in the loop and got this weird output. So I am wondering if it some internal bug?
Reply With Quote
  #6 (permalink)  
Old 11-09-07, 11:44 AM
mab's Avatar
mab mab is offline
Community VIP
 
Join Date: Oct 2005
Location: Denver, Co. USA
Posts: 2,674
Thanks: 0
Thanked 0 Times in 0 Posts
The reason that the key(), current(), and next() inside the foreach() loop are not operating as expected is because the foreach() loop is operating on a copy of the array and the key(), current(), and next() are operating on the actual array. If you comment out the next(), you will see that the key() and current() don't advance.

The real problem appears to be that the reset() statement does not seam to be resetting the actual array pointer (and the previous foreach() loop did not leave the pointer after the last element as it is supposed to), but referencing the array in an assignment statement did reset it.

Short answer - key(), current(), and next() reference the actual array while a foreach() loop uses a copy of the array, don't use key(), current(), and next() inside of a foreach() loop, there is no need (and I will bet the code takes twice as long to execute because you are duplicating what the foreach() is doing inside of the foreach() loop.)

BTW: The , will only work in an echo statement, as it accepts a coma separated list of parameters -
Quote:
void echo ( string $arg1 [, string $...] )
This is not actually concatenating a string using the .
__________________
Error checking, error reporting, and error recovery. If your code does not have these to get it to tell you why it is not working, what makes you think someone in a programming forum will be able to tell you why it is not working???

Last edited by mab; 11-09-07 at 11:47 AM. Reason: add , info
Reply With Quote
  #7 (permalink)  
Old 11-09-07, 12:37 PM
mab's Avatar
mab mab is offline
Community VIP
 
Join Date: Oct 2005
Location: Denver, Co. USA
Posts: 2,674
Thanks: 0
Thanked 0 Times in 0 Posts
I played with the code a bit and the reset() statement does in fact reset the actual array pointer (echo something with key() and current() in it immediately after the reset()) and the previous foreach() loop is leaving the array pointer after the last element as it should.

What I suspect is happening is some short-circuit optimization. When the second (any) foreach() loop sees that the array has not been directly referenced, it is apparently not bothering with the actual array pointer until after the loop finishes (it does appear to be resetting it and incrementing it once, leaving it pointing to the second element for the duration of the loop.)

I tested some more and when the array has been referenced at all (put the $NotUsed = $testArray; after the array() statement and before the first foreach() loop and comment out the one before the second foreach() loop) the foreach() is resetting the actual array pointer but is leaving it pointing to the first element for the duration of the loop.

So, somehow the foreach loop is detecting a "no-reference" state of the array and is either leaving the actual array pointer pointing to the first element or to the second element for the duration of the loop, depending on if the array has been previously referenced or not.

Short answer - use a foreach() loop the way it was meant to be, and don't directly access the array elements using key(), current(), and next() inside of a foreach() loop.
__________________
Error checking, error reporting, and error recovery. If your code does not have these to get it to tell you why it is not working, what makes you think someone in a programming forum will be able to tell you why it is not working???

Last edited by mab; 11-09-07 at 12:41 PM.
Reply With Quote
  #8 (permalink)  
Old 11-12-07, 04:34 PM
divya divya is offline
Newbie Coder
 
Join Date: Nov 2007
Posts: 7
Thanks: 0
Thanked 0 Times in 0 Posts
Thanks for extended testing with this piece of code.

The foreach does operates on the copy of the array. The key(),next() and current() are normally not meant to be used outside the foreach, but could be used for some processing reasons.

But this is clear that the foreach does alter the original internal pointer of the associative array to the second element which should have been the first element.
And somehow it does not alter the original internal pointer if the array is part of the assignment statement just before the foreach loop.

Is this a bug?

Thanks,
Divya


Quote:
Originally Posted by mab View Post
I played with the code a bit and the reset() statement does in fact reset the actual array pointer (echo something with key() and current() in it immediately after the reset()) and the previous foreach() loop is leaving the array pointer after the last element as it should.

What I suspect is happening is some short-circuit optimization. When the second (any) foreach() loop sees that the array has not been directly referenced, it is apparently not bothering with the actual array pointer until after the loop finishes (it does appear to be resetting it and incrementing it once, leaving it pointing to the second element for the duration of the loop.)

I tested some more and when the array has been referenced at all (put the $NotUsed = $testArray; after the array() statement and before the first foreach() loop and comment out the one before the second foreach() loop) the foreach() is resetting the actual array pointer but is leaving it pointing to the first element for the duration of the loop.

So, somehow the foreach loop is detecting a "no-reference" state of the array and is either leaving the actual array pointer pointing to the first element or to the second element for the duration of the loop, depending on if the array has been previously referenced or not.

Short answer - use a foreach() loop the way it was meant to be, and don't directly access the array elements using key(), current(), and next() inside of a foreach() loop.
Reply With Quote
  #9 (permalink)  
Old 11-13-07, 12:38 AM
job0107's Avatar
job0107 job0107 is offline
Community Liaison
 
Join Date: Dec 2006
Location: Tacoma, Washington USA
Posts: 3,454
Thanks: 0
Thanked 140 Times in 137 Posts
In your original code you commented out the reset function.
And that is what you need to get your code to work.
The foreach statement moves the array pointer the first time
it executes, before it makes a copy. So you must reset the pointer once.

Like this:
PHP Code:

<?php
$testArray 
=  array("first"=>"Mon","second"=>"Tuesday","third"=>"Wednesday","fourth"=>"Thrusday");
print_r($testArray);
echo 
"<p><strong>Iterating with key,value </strong></p>";
foreach(
$testArray as $key=>$value)
{
 echo 
"<p>Key: "$key" is $value </p>";
 }
echo 
"<p><strong>Iterating with value </strong></p>";
foreach(
$testArray as $test)
{
 if(!isset(
$sw)){reset($testArray);$sw 1;}
 echo 
"<p>Key: "key($testArray)," Current value: ",current($testArray),"</p>";
 echo 
"<p>Value: $test</p>";
 
next($testArray);
 }
?>
__________________
Jerry Broughton

Last edited by job0107; 11-13-07 at 12:44 AM.
Reply With Quote
  #10 (permalink)  
Old 11-13-07, 08:27 AM
mab's Avatar
mab mab is offline
Community VIP
 
Join Date: Oct 2005
Location: Denver, Co. USA
Posts: 2,674
Thanks: 0
Thanked 0 Times in 0 Posts
In the testing I did, I included the line with the reset() and it does reset the pointer (I echoed a line using key() and current() immediately after it.)

The issue is a foreach() loop does not maintain the actual array pointer inside of the loop, it maintains its own copy of the array pointer, then sets the actual array pointer to be after the last element in the array after the end of the loop.

The foreach() loop provides access to a value or key/value directly through the foreach() language construct. Using key()/current() to access the same things is simply ignoring the definition of the foreach() language construct.

By using key/current/next inside of a foreach() loop, you are executing twice the amount of code, taking twice the amount of processing time, to do something that the foreach() loop was designed to do by itself. There is no common sense reason to be doing this.
__________________
Error checking, error reporting, and error recovery. If your code does not have these to get it to tell you why it is not working, what makes you think someone in a programming forum will be able to tell you why it is not working???

Last edited by mab; 11-13-07 at 08:30 AM.
Reply With Quote
Reply

Bookmarks


Currently Active Users Viewing This Thread: 1 (0 members and 1 guests)
 
Thread Tools
Display Modes

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is Off
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are On

Forum Jump

Similar Threads
Thread Thread Starter Forum Replies Last Post
Classified Ads skipper23 Perl 3 11-22-05 02:22 AM
Foreach Variable/array Scope DAL PHP 5 10-22-05 01:38 PM
formmail problem gscraper Perl 12 08-27-04 03:06 AM
Associative Arrays fxsinus JavaScript 4 03-12-04 09:38 AM
Classified Ads skipper23 Perl 2 12-30-03 03:43 AM


All times are GMT -5. The time now is 07:32 AM.
vBulletin® Copyright ©2000 - 2012, Jelsoft Enterprises Ltd.