Login | Register   
RSS Feed
Download our iPhone app
Browse DevX
Sign up for e-mail newsletters from DevX


Ruby—A Diamond of a Programming Language, Part 2 : Page 5

Get ready to dive deeper into the power and elegance of the language lauded as a possible contender to replace current programming languages.




Full Text Search: The Key to Better Natural Language Queries for NoSQL in Node.js

Data Structures
As with many programming languages, Ruby comes complete with built in data structures to contain and manage data and objects. Arrays are objects that hold a collection of other object references. Arrays are created using square bracket notation and separating object references in the list with commas.


To make it easier to construct an array full of words as above, a special notation is provided to eliminate the double quotes and commas.

presidents= %w[ John Richard Gerald Ronald George William];

It other programming languages, the term “array” often implies a homogenous collection of objects. Not so in Ruby. In Ruby, an array can be a heterogeneous collection of object references. So, the following is a perfectly legal array.

order_date=Date.today() shirt_information=[14.5,”Long”,32,order_date]

Object references are stored sequentially and indexed in the array. Like Java, the indexes start at 0 and the index can be used to retrieve the object reference from the array. Below, the third element (at index of 2) is requested from the shirt_information array created above in the irb. Notice you can use either the square bracket notation or the at method to retrieve object references from the array?

irb(main):003:0> shirt_information[2] => 32 irb(main):004:0> shirt_information.at(2) => 32

Interestingly, you can also reference elements in the array using a “negative index.” A negative index is counted from the end of the array.

irb(main):005:0> shirt_information[-3] => "Long"

Arrays are dynamic, meaning the size of the array changes dynamically depending on your operations. You can add or replace an element in the array using the [index]= operator.

irb(main):013:0> shirt_information => [14.5, "Long", 32, #<Date: 4907585/2,0,2299161>] irb(main):014:0> shirt_information[1]="Medium" #change shirt length => "Medium" irb(main):015:0> shirt_information[4]=49.99 #add shirt cost => 49.99 irb(main):016:0> shirt_information => [14.5, "Medium", 32, #<Date: 4907585/2,0,2299161>, 49.99]

You can also use number pairs and ranges to create new arrays from portions of the array using a [start index, element count] notation or [beginning_index..ending_index] notation.

irb(main):019:0> shirt_information => [14.5, "Long", 32, #<Date: 4907585/2,0,2299161>, 49.99] irb(main):020:0> shirt_dimensions = shirt_information[0,3] => [14.5, "Long", 32] irb(main):021:0> shirt_order = shirt_information[2..5] => [32, #<Date: 4907585/2,0,2299161>, 49.99] irb(main):030:0> shirt_information[-3,2] => [32, #<Date: 4907585/2,0,2299161>]

This notation combined with the assignment operator ([ ]=) gives rise to a very intricate element insert or replacement operations. A beginning/ending index or range can be used in the assignment operator. This can be best understood with some example code.

irb(main):001:0> test_array=["zero", "one", "two", "three", "four"] => ["zero", "one", "two", "three", "four"] irb(main):002:0> #starting at the second element, replace the next two elements with a single element irb(main):003:0* test_array[1,2]=1 => 1 irb(main):004:0> test_array => ["zero", 1, "three", "four"] irb(main):005:0> #insert a new element after the second element (zero as a second parameter indicates “insert”) irb(main):006:0* test_array[2,0]=2 => 2 irb(main):007:0> test_array => ["zero", 1, 2, "three", "four"] irb(main):008:0> #add an array of elements after element 5 irb(main):009:0* test_array[5,0]=[5,6,7] => [5, 6, 7] irb(main):010:0> test_array => ["zero", 1, 2, "three", "four", 5, 6, 7] irb(main):011:0> #replace elements in the index range of 3..4 with the array assigned irb(main):012:0* test_array[3..4]=[3,4] => [3, 4] irb(main):013:0> test_array => ["zero", 1, 2, 3, 4, 5, 6, 7]

Finally, maybe some of the most powerful operations with Ruby arrays are found in the “mathematical” operators that create new arrays from existing arrays. For example, the + operator allows you to create a new array from two arrays concatenated together and the * operator allows you to duplicate or concatenate an array with itself so many times.

irb(main):033:0> shirt_information => [14.5, "Long", 32, #<Date: 4907585/2,0,2299161>, 49.99] irb(main):034:0> pant_information=[34,32,59.99,order_date] => [34, 32, 59.99, #<Date: 4907585/2,0,2299161>] irb(main):035:0> shirt_information + pant_information => [14.5, "Long", 32, #<Date: 4907585/2,0,2299161>, 49.99, 34, 32, 59.99, #<Date: 4907585/2,0,2299161>] irb(main):036:0> shirt_information * 2 => [14.5, "Long", 32, #<Date: 4907585/2,0,2299161>, 49.99, 14.5, "Long", 32, #<Date: 4907585/2,0,2299161>, 49.99] irb(main):037:0> array1 = [2,4,6,8,10] => [2, 4, 6, 8, 10] irb(main):038:0> array2=[3,6,9] => [3, 6, 9] irb(main):039:0> array1 - array2 => [2, 4, 8, 10]

Closely related cousins to Arrays in Ruby are Hashes. The index used to sequence and refer to object references in an array was an integer. The Hash class in Ruby behaves like Array except that it allows any type of object “index” or key to reference objects in the collection. In other programming languages this might be called a dictionary or map or hash map. In general, when working with a hash, you supply two object references for every element in the collection. One object reference is the key and other is what the key points to called the value. The notation used to show what a key object points to is the => symbol. Key/value pairs can be collected between two curly brackets when creating a hash. As an example of a hash, use simple string objects as keys to reference Date objects (values) in a hash.

holidays={"New Year"=>Date.parse("2006-01-02"), "MLB Birthday"=> Date.parse("2006-01-16"), "Washington Birthday"=>Date.parse("2006-02-20"), "Memorial Day"=>Date.parse("2006-05-29"), “July 4th”=>Date.parse(“2006-07-05”)}

To retrieve the Date object for Memorial Day, use the “Memorial Day” string key.

irb(main):004:0> holidays["Memorial Day"] => # irb(main):005:0> holidays["Memorial Day"].to_s => "2006-05-29"

The statement made earlier that “any” object could be used as a key in a Hash is restricted by the fact that objects that serve as keys must respond to the hash method with a hash value that does not change. The hash value of any object is a fix number created by Ruby to uniquely identify an object. The content of a collection object (like an array or hash) is used to determine its hash code. Because the content of a collection object can change, so too can their hash code change; thus instances of Array and Hash cannot serve as keys in a hash object. While hashes provide the convenience of allowing almost any object to serve as the index or key, their disadvantage is that they are not sequential or ordered as are arrays.

As you might expect, there are many additional methods on the Array and Hash classes that allow you to access and modify individual elements in the collection or change the entire collection itself. As shown here, arrays and hashes in Ruby are very powerful and dynamic data structures.

Once you have a collection of object references, one of the most common tasks in programming is to cycle through or “iterate” through the elements in the collection and perform some task. Ruby, like Java, C#, Lisp, and several other programming languages has a built in mechanism for iterating through the elements in an array or hash. The mechanism Ruby provides to iterate is a set of special methods on the collection objects. Methods like each, each_index, delete_if on Array and each, each_key, each_value, each_pair on Hash allow your code to cycle through and take action on the contents of the collection. In fact, many classes in Ruby contain iterator methods. String, for example provides iterator methods to perform tasks on strings separated by a designated character or by bytes. However, before you can understand iterator methods, you need to understand the concept of code blocks in Ruby. For each of the iterator methods are passed a block of code to execute when iterating over members of the collection.

Comment and Contribute






(Maximum characters: 1200). You have 1200 characters left.



Thanks for your registration, follow us on our social networks to keep up-to-date