Blocks and Arrays

Blocks are commonly used to iterate over arrays. The Array class, consequently, provides a number of methods to which blocks are passed.

One useful method is called collect; this passes each element of the array to a block and creates a new array to contain each of the values returned by the block. Here, for example, a block is passed to each of the integers in an array (each integer is assigned to the variable x); the block doubles its value and returns it. The collect method creates a new array containing each of the returned integers in sequence:

2blocks.rb

b3 = [1,2,3].collect{|x| x*2}

The previous example assigns this array to b3:

[2,4,6]

In the next example, the block returns a version of the original strings in which each initial letter is capitalized:

b4 = ["hello","good day","how do you do"].collect{|x| x.capitalize }

So, b4 is now as follows:

["Hello", "Good day", "How do you do"]

The each method of the Array class may look rather similar to collect; it too passes each array element in turn to be processed by the block. However, unlike collect, the each method does not create a new array to contain the returned values:

b5 = ["hello","good day","how do you do"].each{|x| x.capitalize }

This time, b5 is unchanged:

["hello", "good day", "how do you do"]

Recall, however, that some methods—notably those ending with an exclamation mark (!)—actually alter the original objects rather than yielding new values. If you wanted to use the each method to capitalize the strings in the original array, you could use the capitalize! method:

b6 = ["hello","good day", "how do you do"].each{|x| x.capitalize! }

So, b6 is now as follows:

["Hello", "Good day", "How do you do"]

With a bit of thought, you could also use a block to iterate over the characters in a string. First, you need to split off each character from a string. This can be done using the split method of the String class like this:

"hello world".split(//)

The split method divides a string into substrings based on a delimiter and returns an array of these substrings. Here // is a regular expression that defines a zero-length string; this has the effect of returning a single character, so you end up creating an array of all the characters in the string. You can now iterate over this array of characters, returning a capitalized version of each:

a = "hello world".split(//).each{ |x| newstr << x.capitalize }

At each iteration, a capitalized character is appended to newstr, and the following is displayed:

H
HE
HEL
HELL
HELLO
HELLO
HELLO W
HELLO WO
HELLO WOR
HELLO WORL
HELLO WORLD

Because you are using the capitalize method here (with no terminating ! character), the characters in the array a remain as they began, all lowercase, since the capitalize method does not alter the receiver object (here the receiver objects are the characters passed into the block).

Be aware, however, that this code would not work if you were to use the capitalize! method to modify the original characters. This is because capitalize! returns nil when no changes are made, so when the space character is encountered, nil would be returned, and your attempt to append (<<) a nil value to the string newstr would fail.

You could also capitalize a string using the each_byte method. This iterates through the string characters, passing each byte to the block. These bytes take the form of ASCII codes. So, “hello world” would be passed in the form of these numeric values: 104 101 108 108 111 32 119 111 114 108 100.

Obviously, you can’t capitalize an integer, so you need to convert each ASCII value to a character. The chr method of String does this:

a = "hello world".each_byte{|x| newstr << (x.chr).capitalize }
..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
18.119.163.238