Performing Other Array Manipulations
So far, we have covered only about half the array processing functions. Many others will be useful from time to time; we describe some of them next.
Navigating Within an Array: each(), current(), reset(), end(), next(), pos(), and prev()
We mentioned previously that every array has an internal pointer that points to the current element in the array. You indirectly used this pointer earlier when using the each() function, but you can directly use and manipulate this pointer.
If you create a new array, the current pointer is initialized to point to the first element in the array. Calling current( $array_name ) returns the first element.
Calling either next() or each() advances the pointer forward one element. Calling each( $array_name ) returns the current element before advancing the pointer. The function next() behaves slightly differently: Calling next( $array_name ) advances the pointer and then returns the new current element.
You have already seen that reset() returns the pointer to the first element in the array. Similarly, calling end( $array_name ) sends the pointer to the end of the array. The first and last elements in the array are returned by reset() and end(), respectively.
To move through an array in reverse order, you could use end() and prev(). The prev() function is the opposite of next(). It moves the current pointer back one and then returns the new current element.
For example, the following code displays an array in reverse order:
$value = end ($array); while ($value) { echo "$value<br />"; $value = prev($array); }
For example, you can declare $array like this:
$array = array(1, 2, 3);
In this case, the output would appear in a browser as follows:
3 2 1
Using each(), current(), reset(), end(), next(), pos(), and prev(), you can write your own code to navigate through an array in any order.
Applying Any Function to Each Element in an Array: array_walk()
Sometimes you might want to work with or modify every element in an array in the same way. The function array_walk() allows you to do this. The prototype of array_walk() is as follows:
bool array_walk(array arr, string func, [mixed userdata])
Similar to the way you called usort() earlier, array_walk() expects you to declare a function of your own. As you can see, array_walk() takes three parameters. The first, arr, is the array to be processed. The second, func, is the name of a user-defined function that will be applied to each element in the array. The third parameter, userdata, is optional. If you use it, it will be passed through to your function as a parameter. You see how this works shortly.
A handy user-defined function might be one that displays each element with some specified formatting. The following code displays each element on a new line by calling the user-defined function my_print() with each element of $array:
function my_print($value) { echo "$value<br />"; } array_walk($array, 'my_print');
The function you write needs to have a particular signature. For each element in the array, array_walk takes the key and value stored in the array, and anything you passed as userdata, and calls your function like this:
yourfunction(value, key, userdata)
For most uses, your function will be using only the values in the array. For some, you might also need to pass a parameter to your function using the parameter userdata. Occasionally, you might be interested in the key of each element as well as the value. Your function can, as with MyPrint(), choose to ignore the key and userdata parameter.
For a slightly more complicated example, you can write a function that modifies the values in the array and requires a parameter. Although you may not interested in the key, you need to accept it to accept the third parameter:
function my_multiply(&$value, $key, $factor) { $value *= $factor; } array_walk(&$array, 'my_multiply', 3);
This code defines a function, my_multiply(), that will multiply each element in the array by a supplied factor. You need to use the optional third parameter to array_walk() to take a parameter to pass to the function and use it as the factor to multiply by. Because you need this parameter, you must define the function, my_multiply(), to take three parameters: an array element's value ($value), an array element's key ($key), and the parameter ($factor). You can choose to ignore the key.
A subtle point to note is the way $value is passed. The ampersand (&) before the variable name in the definition of my_multiply() means that $value will be passed by reference. Passing by reference allows the function to alter the contents of the array.
We address passing by reference in more detail in Chapter 5. If you are not familiar with the term, for now just note that to pass by reference, you place an ampersand before the variable name.
Counting Elements in an Array: count(), sizeof(), and array_count_values()
You used the function count() in an earlier example to count the number of elements in an array of orders. The function sizeof() serves exactly the same purpose. Both of these functions return the number of elements in an array passed to them. You get a count of one for the number of elements in a normal scalar variable and zero if you pass either an empty array or a variable that has not been set.
The array_count_values() function is more complex. If you call array_count_values($array), this function counts how many times each unique value occurs in the array named $array. (This is the set cardinality of the array.) The function returns an associative array containing a frequency table. This array contains all the unique values from $array as keys. Each key has a numeric value that tells you how many times the corresponding key occurs in $array.
For example, the code
$array = array(4, 5, 1, 2, 3, 1, 2, 1); $ac = array_count_values($array);
creates an array called $ac that contains
Key |
Value |
4 |
1 |
5 |
1 |
1 |
3 |
2 |
2 |
3 |
1 |
This result indicates that 4, 5, and 3 occurred once in $array, 1 occurred three times, and 2 occurred twice.
Converting Arrays to Scalar Variables: extract()
If you have a non-numerically indexed array with a number of key value pairs, you can turn them into a set of scalar variables using the function extract(). The prototype for extract() is as follows:
extract(array var_array [, int extract_type] [, string prefix] );
The purpose of extract() is to take an array and create scalar variables with the names of the keys in the array. The values of these variables are set to the values in the array.
Here is a simple example:
$array = array( 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'); extract($array); echo "$key1 $key2 $key3";
This code produces the following output:
value1 value2 value3
The array has three elements with keys: key1, key2, and key3. Using extract(), you create three scalar variables: $key1, $key2, and $key3. You can see from the output that the values of $key1, $key2, and $key3 are 'value1', 'value2', and 'value3', respectively. These values come from the original array.
The extract() function has two optional parameters: extract_type and prefix. The variable extract_type tells extract() how to handle collisions. These are cases in which a variable already exists with the same name as a key. The default response is to overwrite the existing variable. The allowable values for extract_type are shown in Table 3.2.
Table 3.2 Allowed extract_type Parameters for extract()
Type |
Meaning |
EXTR_OVERWRITE |
Overwrites the existing variable when a collision occurs. |
EXTR_SKIP |
Skips an element when a collision occurs. |
EXTR_PREFIX_SAME |
Creates a variable named $prefix_key when a collision occurs. You must supply prefix. |
EXTR_PREFIX_ALL |
Prefixes all variable names with prefix. You must supply prefix. |
EXTR_PREFIX_INVALID |
Prefixes variable names that would otherwise be invalid (for example, numeric variable names) with prefix. You must supply prefix. |
EXTR_IF_EXISTS |
Extracts only variables that already exist (that is, writes existing variables with values from the array). This parameter was added at version 4.2.0 and is useful for converting, for example, $_REQUEST to a set of valid variables. |
EXTR_PREFIX_IF_EXISTS |
Creates a prefixed version only if the nonprefixed version already exists. This parameter was added at version 4.2.0. |
EXTR_REFS |
Extracts variables as references. This parameter was added at version 4.3.0. |
The two most useful options are EXTR_OVERWRITE (the default) and EXTR_PREFIX_ALL. The other options might be useful occasionally when you know that a particular collision will occur and want that key skipped or prefixed. A simple example using EXTR_PREFIX_ALL follows. You can see that the variables created are called prefix- underscore-keyname:
$array = array( 'key1' => 'value1', 'key2' => 'value2', 'key3' => 'value3'); extract($array, EXTR_PREFIX_ALL, 'my_prefix'); echo "$my_prefix_key1 $my_prefix_key2 $my_prefix_key3";
This code again produces the following output:
value1 value2 value3
Note that for extract() to extract an element, that element's key must be a valid variable name, which means that keys starting with numbers or including spaces are skipped.