Приглашаем посетить
Набоков (nabokov-lit.ru)

4.2 Looping Through Arrays

Previous Table of Contents Next

4.2 Looping Through Arrays

One of the most common things to do with an array is to consider each element in the array individually and process it somehow. This may involve incorporating it into a row of an HTML table or adding its value to a running total.

The easiest way to iterate through each element of an array is with foreach( ). The foreach( ) construct lets you run a code block once for each element in an array. Example 4-7 uses foreach( ) to print an HTML table containing each element in an array.

Example 4-7. Looping with foreach( )
$meal = array('breakfast' => 'Walnut Bun',

              'lunch' => 'Cashew Nuts and White Mushrooms',

              'snack' => 'Dried Mulberries',

              'dinner' => 'Eggplant with Chili Sauce');

print "<table>\n";

foreach ($meal as $key => $value) {

    print "<tr><td>$key</td><td>$value</td></tr>\n";

}

print '</table>';

Example 4-7 prints:

<table>

<tr><td>breakfast</td><td>Walnut Bun</td></tr>

<tr><td>lunch</td><td>Cashew Nuts and White Mushrooms</td></tr>

<tr><td>snack</td><td>Dried Mulberries</td></tr>

<tr><td>dinner</td><td>Eggplant with Chili Sauce</td></tr>

</table>

For each element in $meal, foreach( ) copies the key of the element into $key and the value into $value. Then, it runs the code inside the curly braces. In Example 4-7, that code prints $key and $value with some HTML to make a table row. You can use whatever variable names you want for the key and value inside the code block. If the variable names were in use before the foreach( ), though, they're overwritten with values from the array.

When you're using foreach( ) to print out data in an HTML table, often you want to apply alternating colors or styles to each table row. This is easy to do when you store the alternating color values in a separate array. Then, switch a variable between 0 and 1 each time through the foreach( ) to print the appropriate color. Example 4-8 alternates between the two color values in its $row_color array.

Example 4-8. Alternating table row colors
$row_color = array('red','green');

$color_index = 0;

$meal = array('breakfast' => 'Walnut Bun',

              'lunch' => 'Cashew Nuts and White Mushrooms',

              'snack' => 'Dried Mulberries',

              'dinner' => 'Eggplant with Chili Sauce');

print "<table>\n";

foreach ($meal as $key => $value) {

    print '<tr bgcolor="' . $row_color[$color_index] . '">';

    print "<td>$key</td><td>$value</td></tr>\n";

    // This switches $color_index between 0 and 1

    $color_index = 1 - $color_index;

}

print '</table>';

Example 4-8 prints:

<table>

<tr bgcolor="red"><td>breakfast</td><td>Walnut Bun</td></tr>

<tr bgcolor="green"><td>lunch</td><td>Cashew Nuts and White Mushrooms</td></tr>

<tr bgcolor="red"><td>snack</td><td>Dried Mulberries</td></tr>

<tr bgcolor="green"><td>dinner</td><td>Eggplant with Chili Sauce</td></tr>

</table>

Inside the foreach( ) code block, changing the loop variables like $key and $value doesn't affect the actual array. If you want to change the array, use the $key variable as an index into the array. Example 4-9 uses this technique to double each element in the array.

Example 4-9. Modifying an array with foreach( )
$meals = array('Walnut Bun' => 1,

               'Cashew Nuts and White Mushrooms' => 4.95,

               'Dried Mulberries' => 3.00,

               'Eggplant with Chili Sauce' => 6.50);



foreach ($meals as $dish => $price) {

    // $price = $price * 2 does NOT work

    $meals[$dish] = $meals[$dish] * 2;

}



// Iterate over the array again and print the changed values

foreach ($meals as $dish => $price) {

    printf("The new price of %s is \$%.2f.\n",$dish,$price);

}

Example 4-9 prints:

The new price of Walnut Bun is $2.00.

The new price of Cashew Nuts and White Mushrooms is $9.90.

The new price of Dried Mulberries is $6.00.

The new price of Eggplant with Chili Sauce is $13.00.

There's a more concise form of foreach( ) for use with numeric arrays, shown in Example 4-10.

Example 4-10. Using foreach( ) with numeric arrays
$dinner = array('Sweet Corn and Asparagus',

                'Lemon Chicken',

                'Braised Bamboo Fungus');

foreach ($dinner as $dish) {

    print "You can eat: $dish\n";

}

Example 4-10 prints:

You can eat: Sweet Corn and Asparagus

You can eat: Lemon Chicken

You can eat: Braised Bamboo Fungus

With this form of foreach( ), just specify one variable name after as, and each element value is copied into that variable inside the code block. However, you can't access element keys inside the code block.

To keep track of your position in the array with foreach( ), you have to use a separate variable that you increment each time the foreach( ) code block runs. With for( ), you get the position explicitly in your loop variable. The foreach( ) loop gives you the value of each array element, but the for( ) loop gives you the position of each array element. There's no loop structure that gives you both at once.

So, if you want to know what element you're on as you're iterating through a numeric array, use for( ) instead of foreach( ). Your for( ) loop should depend on a loop variable that starts at 0 and continues up to one less than the number of elements in the array. This is shown in Example 4-11.

Example 4-11. Iterating through a numeric array with for( )
$dinner = array('Sweet Corn and Asparagus',

                'Lemon Chicken',

                'Braised Bamboo Fungus');

for ($i = 0, $num_dishes = count($dinner); $i < $num_dishes; $i++) {

  print "Dish number $i is $dinner[$i]\n";

}

Example 4-11 prints:

Dish number 0 is Sweet Corn and Asparagus

Dish number 1 is Lemon Chicken

Dish number 2 is Braised Bamboo Fungus

When iterating through an array with for( ), you have a running counter available of which array element you're on. Use this counter with the modulus operator to alternate table row colors, as shown in Example 4-12.

Example 4-12. Alternating table row colors with for( )
$row_color = array('red','green');

$dinner = array('Sweet Corn and Asparagus',

                'Lemon Chicken',

                'Braised Bamboo Fungus');

print "<table>\n";



for ($i = 0, $num_dishes = count($dinner); $i < $num_dishes; $i++) {

    print '<tr bgcolor="' . $row_color[$i % 2] . '">';

    print "<td>Element $i</td><td>$dinner[$i]</td></tr>\n";

}

print '</table>';

Example 4-12 computes the correct table row color with $i % 2. This value alternates between 0 and 1 as $i alternates between even and odd. There's no need to use a separate variable, such as $color_index in Example 4-8, to hold the appropriate row color. Example 4-12 prints:

<table>

<tr bgcolor="red"><td>Element 0</td><td>Sweet Corn and Asparagus</td></tr>

<tr bgcolor="green"><td>Element 1</td><td>Lemon Chicken</td></tr>

<tr bgcolor="red"><td>Element 2</td><td>Braised Bamboo Fungus</td></tr>

</table>

When you iterate through an array using foreach( ), the elements are accessed in the order that they were added to the array. The first element added is accessed first, the second element added is accessed next, and so on. If you have a numeric array whose elements were added in a different order than how their keys would usually be ordered, this could produce unexpected results. Example 4-13 doesn't print out array elements in numeric or alphabetic order.

Example 4-13. Array element order and foreach( )
$letters[0] = 'A';

$letters[1] = 'B';

$letters[3] = 'D';

$letters[2] = 'C';



foreach ($letters as $letter) {

    print $letter;

}

Example 4-13 prints:

ABDC

To guarantee that elements are accessed in numerical key order, use for( ) to iterate through the loop:

for ($i = 0, $num_letters = count($letters); $i < $num_letters; $i++) {

    print $letters[$i];

}

This prints:

ABCD

If you're looking for a specific element in an array, you don't need to iterate through the entire array to find it. There are more efficient ways to locate a particular element. To check for an element with a certain key, use array_key_exists( ), shown in Example 4-14. This function returns true if an element with the provided key exists in the provided array.

Example 4-14. Checking for an element with a particular key
$meals = array('Walnut Bun' => 1,

               'Cashew Nuts and White Mushrooms' => 4.95,

               'Dried Mulberries' => 3.00,

               'Eggplant with Chili Sauce' => 6.50,

               'Shrimp Puffs' => 0); // Shrimp Puffs are free!

$books = array("The Eater's Guide to Chinese Characters",

               'How to Cook and Eat in Chinese');



// This is true

if (array_key_exists('Shrimp Puffs',$meals)) {

    print "Yes, we have Shrimp Puffs";

}

// This is false

if (array_key_exists('Steak Sandwich',$meals)) {

    print "We have a Steak Sandwich";

}

// This is true

if (array_key_exists(1, $books)) {

    print "Element 1 is How to Cook in Eat in Chinese";

}

To check for an element with a particular value, use in_array( ), as shown in Example 4-15.

Example 4-15. Checking for an element with a particular value
$meals = array('Walnut Bun' => 1,

               'Cashew Nuts and White Mushrooms' => 4.95,

               'Dried Mulberries' => 3.00,

               'Eggplant with Chili Sauce' => 6.50,

               'Shrimp Puffs' => 0); 

$books = array("The Eater's Guide to Chinese Characters",

               'How to Cook and Eat in Chinese');



// This is true: key Dried Mulberries has value 3.00 

if (in_array(3, $meals)) {

  print 'There is a $3 item.';

}

// This is true

if (in_array('How to Cook and Eat in Chinese', $books)) {

  print "We have How to Cook and Eat in Chinese";

}

// This is false: in_array( ) is case-sensitive

if (in_array("the eater's guide to chinese characters", $books)) {

  print "We have the Eater's Guide to Chinese Characters.";

}

The in_array( ) function returns true if it finds an element with the given value. It is case-sensitive when it compares strings. The array_search( ) function is similar to in_array( ), but if it finds an element, it returns the element key instead of true. In Example 4-16, array_search( ) returns the name of the dish that costs $6.50.

Example 4-16. Finding an element with a particular value
$meals = array('Walnut Bun' => 1,

               'Cashew Nuts and White Mushrooms' => 4.95,

               'Dried Mulberries' => 3.00,

               'Eggplant with Chili Sauce' => 6.50,

               'Shrimp Puffs' => 0); 



$dish = array_search(6.50, $meals);

if ($dish) {

    print "$dish costs \$6.50";

}

Example 4-16 prints:

Eggplant with Chili Sauce costs $6.50

    Previous Table of Contents Next