Ruby程序快速入门之数据结构


         就象许多程序语言一样,Ruby也提供了完整的数据结构来存储和管理数据与对象。数组是使用方括号和用逗号隔开的单个对象参考列表创建的。

presidents=["John","Richard","Gerald","Ronald","George","William"];

   为了更为容易地创建一个充满单词的数组,Ruby提供了一个特殊的标志来消除双引号和逗号,见下面例子:

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

   在其它编程语言中,"数组"一词经常意味着一组相同性质的对象的集合。但在Ruby中,不是这样。在Ruby中,一个"数组"可以是由不同性质的对象参考组成的集合。因此,下面是有效的数组表达形式:

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

   在这个数组中,对象参考按顺序存储并索引。象Java一样,索引从0开始,索引可用来从数组中检索对象参考。下面的示例中请求的是,上面创建的shirt_information数组中的第3个元素(索引为2)。注意,你可以使用方括号标志或at方法来检索数组中的对象参考。

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

   有趣的是,你还可以使用一个负数索引来引用数组中的元素。一个负数索引是从数组尾部开始计数的。

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

   数组是动态的,意味着数组的大小可以根据你的操作而动态地改变。你可以使用[index]=操作符来添加或替换一个数组中的元素。

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]

   你也可以使用数字对和范围来由数组的一部分创建一个新数组,通过使用一个[开始索引,元素数目]标志或[开始索引...结束索引]标志。

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>]

   这个结合了赋值运算符([]=)的标志将产生一个很复杂的元素插入或代替操作。一个开始/结束索引或范围可以用在赋值操作符中。具体使用请参考下面的示例:

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 one
(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]

   最后,也许Ruby数组中最有力量的运算可以从数学操作符中找到答案-它们能够从现在数组创建新的数组。例如,+操作符允许你由两个数组的连接创建一个新数组,而*操作符允许你复制或连接一个数组自身若干次。

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]

   在Ruby中,与数组联系最密切的就是哈希表。在一个数组中,索引是一个整数。在Ruby中Hash类行为上与Array非常相似,但是它允许在集合中出现到参考对象的任何类型的对象"索引"(或键)。在另外的程序语言中,这可能被称为一个字典或地图或哈希地图。一般地,当使用哈希表时,你应该为集合中的每个元素提供两个对象参考。其中,一个对象参考用作键,另一个用作该键所指对象(即"值")。用于指示一个键对象所指内容的标志是=>符号。当创建哈希表时,键/值对可以在两个大括号之间被收集。作为一个哈希表的例子,你可以在哈希表中使用简单的字符串对象作为键来引用Date对象(值)。

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")}

   为了检索纪念日的Date对象,你可以使用"Memorial Day"字符串键。

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

  如你所想,在数组和哈希表中还有另外许多方法来允许你存取和修改集合中的单个元素或改变全部集合本身。因此,在Ruby中,数组和哈希表都是功能极强的动态的数据结构。

  一旦你有一个对象参考的集合,那么在编程中最常用的一项任务就是遍历该集合中的每一个元素并执行某些操作。Ruby当然也提供了数组和哈希表中的类似机制。Ruby提供的实现遍历集合的机制是该集合对象上的一组方法。Array中的方法(如each,each_index,delete_if)和Hash中的方法(如each,each_key,each_value,each_pair)允许你的编码进行集合遍历并执行特定的任务。事实上,Ruby中的许多类都包含迭代子(iterator)方法。例如,String就提供了一个iterator方法来执行字符串的以字符或字节为单位的遍历任务。然而,在你理解iterator方法前,你首先需要理解Ruby中代码块的概念。因为当遍历集合中的元素时,对于每一个iterator方法,都是通过传递一个代码块来执行的。