Tài liệu hạn chế xem trước, để xem đầy đủ mời bạn chọn Tải xuống
1
/ 67 trang
THÔNG TIN TÀI LIỆU
Thông tin cơ bản
Định dạng
Số trang
67
Dung lượng
633,53 KB
Nội dung
Beginning with PHP 5.0.2, you can cause the array returned by this function to preserve the indexes of the original by passing an additional argument of TRUE: $slice2 = array_slice($languages, 2, count($languages) - 2, TRUE); printf("<pre>Slice 2:\n%s</pre>\n", var_export($slice2, TRUE)); ?> How It Works You can see how this works by examining the output of the previous code and comparing $slice1 and $slice2: Original array: array ( 0 => 'French', 1 => 'German', 2 => 'Russian', 3 => 'Chinese', 4 => 'Hindi', 5 => 'Quechua', 6 => 'Spanish', 7 => 'Hausa', ) Slice 1: array ( 0 => 'Russian', 1 => 'Chinese', 2 => 'Hindi', 3 => 'Quechua', 4 => 'Spanish', 5 => 'Hausa', ) Slice 2: array ( 2 => 'Russian', 3 => 'Chinese', 4 => 'Hindi', 5 => 'Quechua', 6 => 'Spanish', 7 => 'Hausa', ) 4-21 ■ EXTRACTING A PORTION OF AN ARRAY 153 5092_Ch04_CMP4 8/26/05 3:02 PM Page 153 You can also use negative values for $offset and/or $length. If $offset is negative, then the slice returned will start abs($offset) elements from the end of the array; if $length is neg- ative, then the slice will end abs($length) elements from the end of the array. For instance, given the following: $slice3 = array_slice($languages, -6, -2, TRUE); then $slice3 will be identical to $slice2 from the previous example. Finally, you can obtain a slice consisting of all elements of an array beginning with the ele- ment at index $offset all the way through to the end of the array simply by omitting the $length argument. Assuming that $languages is the same array as defined in the last two examples, then the following: $last3 = array_slice($languages, -3); printf("<p>Last 3: %s</p>\n", var_export($last3, TRUE)); will produce this output: Last 3: array ( 0 => 'Quechua', 1 => 'Spanish', 2 => 'Hausa', ) Note that if you want to preserve the original keys, you must supply $length as well as $preserve_keys, as using 0 (or any value that converts to 0, such as an empty string or NULL) for $length will return an empty array. To get a slice consisting of the last three elements in $languages while preserving the keys, you would need to use something like this: $last3 = array_slice($languages, -3, 3, TRUE); printf("<p>Last 3: %s</p>\n", var_export($last3, TRUE)); This will produce the expected result, as shown here: Last 3: array ( 5 => 'Quechua', 6 => 'Spanish', 7 => 'Hausa', ) 4-22. Extracting Values from Arrays with extract() When working with an array, it is sometimes possible to save yourself some time and typing by extracting its elements into simple variables. You do this using the extract() function. This func- tion works by creating a set of variables whose names are taken from the associative array keys and then setting the variables values to the array element values. We find this function particu- larly handy when handling rows returned from database queries, such as those returned by mysql_fetch_assoc() and mysqli_fetch_assoc(), but you can use this function anytime you are obliged to work with arrays, especially those with many elements. The Code <?php $customer = array('first' => 'Bill', 'last' => 'Jones', 'age' => 24, 'street' => '123 Main St.', 'city' => 'Pacifica', 'state' => 'California'); 4-22 ■ EXTRACTING VALUES FROM ARRAYS WITH EXTRACT()154 5092_Ch04_CMP4 8/26/05 3:02 PM Page 154 extract($customer); print "<p>$first $last is $age years old, and lives in $city, $state.</p>"; extract($customer, EXTR_PREFIX_ALL, 'cust'); print "<p>$cust_first $cust_last is $cust_age years old, and lives in $cust_city, $cust_state.</p>"; ?> The print statements each output the following sentence: Bill Jones is 24 years old, and lives in Pacifica, California. Variations extract() offers some additional options that can be helpful when the array keys might not be legal variable identifiers or when you want to avoid overwriting existing variables that might have the same name. (By default, extract() will overwrite such variables.) If you need to see what variables are currently defined, you can call get_defined_vars() to obtain an array of all their names. EXTR_PREFIX_ALL adds a prefix string to the beginning of each key in the original array. This option and the other extract() options that add a prefix to extracted variable names automatically add an underscore character to the prefix. For example, the following will out- put each of the values in the $scores array, in turn, on a separate line: <?php $scores = array(91, 56, 87, 79); extract($scores, EXTR_PREFIX_ALL, "score"); print "<p>$score_0</p>"; print "<p>$score_1</p>"; print "<p>$score_2</p>"; print "<p>$score_3</p>"; ?> Another extremely handy option is EXTR_REFS, which extracts the variables as references to the original associative array elements. The following code shows an example, which also shows how you can combine options passed to extract() by ORing them together using the pipe (|) operator. In this case, you will add the prefix pts to each array key and then make each variable that results into a reference. 4-22 ■ EXTRACTING VALUES FROM ARRAYS WITH EXTRACT() 155 5092_Ch04_CMP4 8/26/05 3:02 PM Page 155 <?php $points = array('home' => 21, 'away' => 13); extract($points, EXTR_REFS|EXTR_PREFIX_ALL, 'pts'); $pts_home -= 4; $pts_away += 6; printf("<p>%s</p>", var_export($points, TRUE)); ?> Because the extracted variables are references, updating their values updates those of the corresponding elements in the original array: array ( 'home' => 17, 'away' => 19, ) You can pass several other options to extract() to exercise more fine-grained control over when variables are or are not overwritten as well as when variable names are or are not prefixed; however, we find that EXTR_PREFIX_ALL and EXTR_REFS satisfy most requirements, so we will let you look up the others in the PHP manual if you are interested. 4-23. Extracting Values from an Array Using list() The list() operator is technically not a function, even though it looks like one. It is also useful for obtaining values, particularly when dealing with indexed arrays. The easiest way to explain what list() does is to show you first and then explain afterward, so the following simple example gets things started. The Code <?php $scores = array(88, 75, 91, 84); list($maths, $english, $history, $biology) = $scores; printf("<p>Maths: %d; English: %d; History: %d; Biology: %d.</p>\n", $maths, $english, $history, $biology); ?> As you might expect, the output from this is as follows: Maths: 88; English: 75; History: 91; Biology: 84. 4-23 ■ EXTRACTING VALUES FROM AN ARRAY USING LIST()156 5092_Ch04_CMP4 8/26/05 3:02 PM Page 156 How It Works list() works by assigning values from the array on the right side of the equals sign to the vari- ables passed to it, in order. So, in this example, $maths was set equal to $scores[0], $english to $scores[1], and so on. Variations If some values in the array do not interest you, you can skip them by marking their places with an “empty” comma, like so: <?php $scores = array(88, 75, 91, 84); list($maths, , $history) = $scores; # using the @ operator to suppress a warning about the undefined variables @printf("<p>Maths: %d; English: %d; History: %d; Biology: %d.</p>\n", $maths, $english, $history, $biology); ?> Although only three array positions have been marked, this is completely permissible; list() simply quits trying to make any assignments after it is finished with all the variables you have supplied. Since %d was used to mark the place of the undefined variable, its value is coerced to integer 0, as shown here: Maths: 88; English: 75; History: 0; Biology: 84. If you try to use more variables with list() than there are elements in the array, you may get a warning about an undefined index. You can suppress this warning with the @ operator (also known as the error suppression operator). However, those variables will remain unset, as shown here: <?php $scores = array(88, 75); @list($maths, $english, $history) = $scores; @printf("<p>Maths: %d; English: %d; History: %d; Biology: %d.</p>\n", $maths, $english, $history, $biology); ?> This is the output: Maths: 88; English: 75; History: 0; Biology: 0. Note that list() ignores elements with string keys. 4-23 ■ EXTRACTING VALUES FROM AN ARRAY USING LIST() 157 5092_Ch04_CMP4 8/26/05 3:02 PM Page 157 4-24. Combining Arrays We have already discussed how to insert arrays into one another and have shown how to write a function to help you do so. Now you will tackle something a bit different: combining two indexed arrays to obtain an associative array. For example, suppose you have two arrays defined as shown: $colors = array('red', 'yellow', 'green'); $flavors = array('apple', 'banana', 'lime'); And suppose you would like to combine these into a single array that looks like this: $fruit = array('red' => 'apple', 'yellow' => 'banana', 'green' => 'lime'); You might think that this requires writing some code that loops through both arrays, assigning one string as a key and the other as its corresponding value, perhaps something like this: $fruit = array(); $limit = count($colors); for($i = 0; $i < $limit; $i++) $fruit[$colors[$i]] = $flavors[$i]; Of course, then you are obligated to perform some checks. Are the arrays the same length? Are they both in fact arrays? Fortunately, PHP has a function that handles all these issues for you. The Code <?php $colors = array('red', 'yellow', 'green'); $flavors = array('apple', 'banana', 'lime'); # same size as $colors $tastes = array('sweet', 'sour'); # different size $prices = array(); # empty $name = 'lemon'; # not an array $arrays = array('name' => $name, 'prices' => $prices, 'flavors' => $flavors, 'tastes' => $tastes); foreach($arrays as $key => $value) { if($fruits = @array_combine($colors, $value)) printf("<pre>%s</pre>\n", var_export($fruits, TRUE)); else printf("<p>Couldn't combine \$colors and \$%s.</p>", $key); } ?> 4-24 ■ COMBINING ARRAYS158 5092_Ch04_CMP4 8/26/05 3:02 PM Page 158 You are using the @ operator in this example to suppress any warnings or errors triggered by passing invalid parameters to array_combine() so that you can handle those using if else. Here is the output from this code: Couldn't combine $colors and $name. Couldn't combine $colors and $prices. array ( 'red' => 'apple', 'yellow' => 'banana', 'green' => 'lime', ) Couldn't combine $colors and $tastes. How It Works array_combine() takes two arrays as arguments, attempts to assign the values from the first arrays as keys to the values found in the second, and returns an associative array if it succeeds. If it fails for any reason (if both arguments are not arrays, if either or both of them are empty, or if they do not contain the same number of values), the function returns FALSE. 4-25. Obtaining Array Keys and Values What about the converse of the problem you looked at in the previous section? In other words, what if you have an associative array named $fruits that is defined as shown here: $fruits = array('red' => 'apple', 'yellow' => 'banana', 'green' => 'lime'); and you like to work with just the colors of the fruits, or just their names? PHP 5 provides a pair of functions intended to make it easy to do this: array_keys() returns an array consisting of only the keys of the array that it acts on, and array_values() returns an array consisting of only the values of the original array. What follows is a simple example in which we have defined an array_display() function to cut down on the repetition of code. The Code <?php function array_display($array, $pre=FALSE) # set optional 2nd argument to { # TRUE for preformatted tree display $tag = $pre ? 'pre' : 'p'; printf("<%s>%s</%s>\n", $tag, var_export($array, TRUE), $tag); } $fruits = array('red' => 'apple', 'yellow' => 'banana', 'green' => 'lime'); 4-25 ■ OBTAINING ARRAY KEYS AND VALUES 159 5092_Ch04_CMP4 8/26/05 3:02 PM Page 159 $colors = array_keys($fruits); $flavors = array_values($fruits); array_display($fruits); array_display($colors); array_display($flavors); ?> How It Works This is pretty straightforward stuff. You start with the associative array $fruits as defined pre- viously. You then use array_keys() to get the keys from $fruit and assign its return value to the variable $colors. Next you use array_values() to get its values, assigning that function’s return value to $flavors. Finally, you output all three variables using array_display(), which is really nothing more than a wrapper for the var_export() function you looked at earlier in the chapter (in recipe 4-8). The result is easy enough to predict, but we will show it to you any- way for the sake of completeness: array ( 'red' => 'apple', 'yellow' => 'banana', 'green' => 'lime', ) array ( 0 => 'red', 1 => 'yellow', 2 => 'green', ) array ( 0 => 'apple', 1 => 'banana', 2 => 'lime', ) ■Tip If you use array_values() on an indexed array, you will just obtain an array whose structure is identical to the first one, with one important exception: its indexes will be reordered. This can be a handy way to “compact” sparse arrays. 4-26.Working with Unique Values Often you will find yourself dealing with sets of data (arrays) containing duplicate values. Although nothing is wrong with this in and of itself, many times you will be interested only in unique values. For example, suppose you are involved with internationalizing a website, and you are working with some logging data concerning countries from which your site has had visitors and the languages spoken in those countries. Let’s assume you have already parsed the log files and have ended up with an array defined as follows: $countries = array( 'USA' => 'English', 'Spain' => 'Spanish', 'Brazil' => 'Portuguese', 'UK' => 'English', 'Mexico' => 'Spanish', 'Germany' => 'German', 'Colombia' => 'Spanish', 'Canada' => 'English', 'Russia' => 'Russian', 'Austria' => 'German', 'France' => 'French', 'Argentina' => 'Spanish'); 4-26 ■ WORKING WITH UNIQUE VALUES160 5092_Ch04_CMP4 8/26/05 3:02 PM Page 160 To get the unique values in this array, all that is necessary is to use the built-in array_unique() function, as shown next. The Code $languages = array_unique($countries); printf("<pre>%s</pre>\n", var_export($languages, TRUE)); The output looks like this: array ( 'USA' => 'English', 'Spain' => 'Spanish', 'Brazil' => 'Portuguese', 'Germany' => 'German', 'Russia' => 'Russian', 'France' => 'French', ) How It Works The array_unique() function returns an array from which all duplicate values have been removed. In cases of duplicate values, only the first element having that value is included each time. (This can occasionally prove useful.) The key associated with each of these values is preserved, as you can see in the previous output. This is true whether the array in question is associative or indexed. If you want only the values, without the keys, you will need to use the array_values() function (discussed in the previous section) on the result. 4-27. Getting and Displaying Counts of Array Values Another frequent task is getting the number of elements that have unique values. The follow- ing example shows one way you can do this, as applied to the $countries array defined in the previous recipe. The Code <?php $language_counts = array_count_values($countries); ?> <table border="1" cellpadding="3" cellspacing="0"> <tbody> <tr><th>Language</th><th>Number<br />of<br />Countries</th></tr> <?php foreach($language_counts as $language => $number) print " <tr><td>$language</td><td>$number</td></tr>\n"; ?> </tbody> </table> 4-27 ■ GETTING AND DISPLAYING COUNTS OF ARRAY VALUES 161 5092_Ch04_CMP4 8/26/05 3:02 PM Page 161 How It Works This works by using the function array_count_values(), which creates a new array whose keys are the values of the array passed to it as a parameter and whose values are the number of times each of those values occurs in the original array. We have dressed up the output just a bit this time by using a HTML table. To obtain this, just loop through the $language_count array, writing a new two-column row for each element and inserting the key into one table cell and the value into another cell. Figure 4-1 shows the result as viewed in a typical web browser. Figure 4-1. Output of the countries and languages example (counts of unique values) Notice that the keys of this array are the unique values from the original array. In other words, array_keys($language_count) is identical to array_values(array_unique($countries)). Finding and Working with Array Values If you know the key for a given array element, whether the key is a string or an integer, finding the matching value is trivial. Doing the opposite is not that difficult, but it does require a bit more effort. In this section, we will show you how to answer questions such as these: • Does an element with a given value exist in an array? • Does an array contain an element with a given key? •At what position can you find an element with a desired value in an array? That is, what key or keys correspond to the value being sought? 4-27 ■ GETTING AND DISPLAYING COUNTS OF ARRAY VALUES162 5092_Ch04_CMP4 8/26/05 3:02 PM Page 162 [...]... (returns a number or FALSE if an average cannot be calculated): # mixed array_average(array $array) function array_average($array) { $retval = FALSE; if(is_array($array) && count($array)) # # $retval = array_sum($array) / count($array); # # return $retval; } if the argument is an array with at least one element divide the sum of the element values by the number of values 50 92_Ch04_CMP4 8/26/ 05 3: 02 PM Page... function are the name of the callback function followed by one or more array variables This callback function works somewhat differently than the one that is used by array_walk() Its prototype is as follows: mixed funcname(array $arr1[, array $arr2[, array $arr3[, ]]]) In other words, the callback takes one or more array variables as parameters, and these parameters must be the same number of array variables... its signature requires only a single parameter (a reference to the current array element’s value) function modify(&$value) { $value *= 1 .5; } $array = array(10, -3 .5, 2, 7); array_display($array, TRUE); array containing some numbers display it as defined array_walk($array, 'modify'); array_display($array, TRUE); # # apply modify() to all the elements in $array display the modified array ?> # # 50 92_Ch04_CMP4... use array_walk(), array_map(), and array_filter() 4 -33 Applying Functions to Array Elements Using array_walk() The following example shows the simplest case for using array_walk() to apply a function to each element of an array; you will apply a function named modify() to each element of an array named $array The outcome you are trying to achieve in this case is to multiply each number in $array by a. .. on one or more arrays; think of it as mapping from one array (or set of arrays) to another array It does not modify the original array(s) and can access only the values of the array(s), not the keys In addition, you can’t pass a user value to it The callback function used with array_map() must return a value, and array_map() itself returns an array If more than one array is used, the arrays do not need... 8/26/ 05 3: 02 PM Page 171 4 -33 ■ APPLYING FUNCTIONS TO ARRAY ELEMENTS USING ARRAY_WALK() Here is the output of this script, showing that the values stored in $array have indeed been updated by the callback function: array ( 0 => 10, 1 => -3 .5, 2 => 2, 3 => 7, ) array ( 0 => 15, 1 => -5. 25, 2 => 3, 3 => 10 .5, ) How It Works The prototype for array_walk() is as follows: bool array_walk(array &$array, string... implode('', array_map('chr', range (32 , 255 ))); You can also use the array_map() function without any callback function to generate nested arrays See recipe 4-24 for an example 50 92_Ch04_CMP4 8/26/ 05 3: 02 PM Page 1 75 4- 35 ■ FILTERING ARRAYS USING ARRAY_FILTER() 4- 35 Filtering Arrays Using array_filter() In the previous two sections, you had a chance to see how you can use a function to modify all the elements... this example, the original array keys are preserved The callback function can be virtually anything you like, as long as it takes a single input parameter (corresponding to an array element’s value) and returns a boolean The only other restriction is that the original array may not be altered by the callback function Variations A quick way to rid an array of “empty” array elements is to call array_filter()... more than one user value to the callback function, you will need Tip to pass it via some structure such as an array, as there can be only one data variable 171 50 92_Ch04_CMP4 172 8/26/ 05 3: 02 PM Page 172 4 -33 ■ APPLYING FUNCTIONS TO ARRAY ELEMENTS USING ARRAY_WALK() Variations Here is a slightly more complex example that uses both the array key and a passed-in value to modify each element value: < ?php. .. variables as passed to array_map() When you pass an array variable to array_map(), the callback function actually “sees” a single element of this array at a time Also, do not forget that the first argument to array_map() is a string and must be quoted This means that since the name of the callback function in the example is safe_sqrt, you need to refer to it as "safe_sqrt" (including the quotation marks) . value of an array's elements # prototype (returns a number or FALSE if an average cannot be calculated): # mixed array_average(array $array) function array_average($array) { $retval = FALSE; if(is_array($array). Code < ?php $colors = array('red', 'yellow', 'green'); $flavors = array('apple', 'banana', 'lime'); # same size as $colors $tastes = array('sweet',. 'English', 'Russia' => 'Russian', 'Austria' => 'German', 'France' => 'French', 'Argentina' => 'Spanish'); A natural