Thursday, October 16, 2008

(14)Ruby中的数组Arrays

Ruby中的数字就是一系列的对象,你可以通过位置或者说索引来访问数组中的元素。在Ruby中数组的第一个元素的索引是0,数组的长度是数组中元素的个数,Ruby数组允许负数索引,最后一个元素的索引是-1,倒数第二个的索引是-2,一次类推,如果你试图使用一个超出范围的索引方法数组你会得到一个nil值,而不会出现异常。
Ruby的数组是可变的,而且无类型的,也就是说你可以在任何时候改变数组内的元素,数组内的元素与不必全部是相同的类型。另外,数字的长度是动态可变的,如果你向其中增加一个元素,数组的长度就会自动扩展,如果你用一个越界索引给数组赋值,它会用一个nil值来扩展数组。
声明一个数组要使用[],其中的元素用逗号分隔:

[1, 2, 3]         #  一个包含3个Fixnum对象的数组。
[-10...0, 0..10,] # 这个数组包含两个Range对象,结尾的逗号是允许的。
[[1,2],[3,4],[5]] # 包含数组的数组
[x+y, x-y, x*y] # 数组元素还可以是表达式
[] # 空数组的长度为0

用%w方式你可以把用分割符号包含的;用空格隔开的不同字符串定义为一个数组:
words = %w[this is a test]  # 等同于: ['this', 'is', 'a', 'test']
open = %w| ( [ { < | # 等同于: ['(', '[', '{', '<']
white = %W(\s \t \r \n) # 等同于: ["\s", "\t", "\r", "\n"]

用%w或%W定义数组的方式类似于用%q和%Q定义字符串,分界符号的规则也一样,在分界符号中的元素无需分号('',“”)包含,无需逗号分隔,不同元素之间用空格隔开。
你还可以通过Array.new 来定义数组,这种方式可以让你通过程序化的手段还初始化数组:
empty = Array.new       # []: 创建一个空的数组
nils = Array.new(3) # [nil, nil, nil]: 包含3个nil的数组
zeros = Array.new(4, 0) # [0, 0, 0, 0]: 创建包含4个0的数组
copy = Array.new(nils) # 创建另一个数组对象的拷贝
count = Array.new(3) {|i| i+1} # [1,2,3]: 通过计算得到的数组,你可以在数组声明后加上一个块,来填充数组

可以通过[一个整数索引] 的方式获得数组元素的值。
a = [0, 1, 4, 9, 16]   # 创建一个数组
a[0] # 第一个元素是 0
a[-1] # 最后一个元素是 16
a[-2] # 倒数第二个元素是 9
a[a.size-1] # 另一种获得最后一个元素的方法
a[-a.size] # 另一种获得第一个元素的方法
a[8] # 越界访问会得到一个 nil值
a[-8] # 越界访问会得到一个 nil值

可以通过赋值的方法修改数字内的元素:
a[0] = "zero"   # a 变成 ["zero", 1, 4, 9, 16]
a[-1] = 1..16 # a 变成 ["zero", 1, 4, 9, 1..16]
a[8] = 64 # a 变成 ["zero", 1, 4, 9, 1..16, nil, nil, nil, 64],增加了新的元素。
a[-9] = 81 # 这里会抛出异常,你不能向数组第一个元素之前赋值

和String对象的操作一样,你同样可以使用两个整数下标或者一个Range对象下标的方式获得一个子数组:
a = ('a'..'e').to_a   # to_a方法将一个Range对象转换为数组 ['a', 'b', 'c', 'd', 'e']
a[0,0] # []: 得到一个空的数组
a[1,1] # ['b']: 得到包含一个元素的数组
a[-2,2] # ['d','e']: 得到包含最后两个元素的数组
a[0..2] # ['a', 'b', 'c']: 包含前面3个元素的数组
a[-2..-1] # ['d','e']: 通过Range的方式获得最后两个元素
a[0...-1] # ['a', 'b', 'c', 'd']: 除最后一个元素外所以元素的数组

可以通过赋值的操作将数组中的子数组修改成其他的内容:
a[0,2] = ['A', 'B']      # a 变成了 ['A', 'B', 'c', 'd', 'e']
a[2...5]=['C', 'D', 'E'] # a 变成了['A', 'B', 'C', 'D', 'E']
a[0,0] = [1,2,3] # 在数组 a之前增加3个元素
a[0..2] = [] # 删除这些元素
a[-1,1] = ['Z'] # 用一个新值替换最后一个元素
a[-1,1] = 'Z' # 如果只修改一个元素,赋值的对象不必一定是数组
a[-2,2] = nil # 在Ruby 1.8中会删除最后两个元素; 在Ruby 1.9中会将最后两个元素替换为nil对象。

你还可以用+符号链接两个数组:
a = [1, 2, 3] + [4, 5]    # [1, 2, 3, 4, 5]
a = a + [[6, 7, 8]] # [1, 2, 3, 4, 5, [6, 7, 8]]
a = a + 9 # 这里会抛出异常,因为只有都是数组的情况下才可以“相加

你还可以使用-符号来从数组中移除指定的元素:


a=['a', 'b', 'c', 'd', 'e']
b=['b', 'c', 'b']
c=a-b

puts "a:#{a},b:#{b},c:#{c}"

输出结果是:
a:["a", "b", "c", "d", "e"],b:["b", "c", "b"],c:["a", "d", "e"]

包含在b中的元素被从a中移除了,但是这个操作不会改变数组a和b本身,只是返回计算结果的拷贝。
我们前面提到的+操作创建了一个链接后的新的数组但是不改变数组本身,而<<会向数组中追加元素,数组本身的内容也发生了改变
a = []        #创建空的数组
a << 1 # a 变成 [1]
a << 2 << 3 # a 变成 [1, 2, 3]
a << [4,5,6] # a 变成 [1, 2, 3, [4, 5, 6]]

和String一样数组也提供了乘法操作:
a = [0] * 8    # [0, 0, 0, 0, 0, 0, 0, 0]

数组对象还引入了布尔操作符:|和&,用他们来取两个数组的交集和并集。|操作将两个数组的重复元素移除并返回两个数组的并集,&操作返回两个数组的交集。
a = [1, 1, 2, 2, 3, 3, 4]
b = [5, 5, 4, 4, 3, 3, 2]
a | b # [1, 2, 3, 4, 5]: 重复元素被移除
b | a # [5, 4, 3, 2, 1]: 元素内容相同,但是顺序变了
a & b # [2, 3, 4]
b & a # [4, 3, 2]

Ruby为数组定义了一系列非常有用的方法,我们这里只介绍一下each方法:
a = ('A'..'Z').to_a    # 创建一个数组
a.each {|x| print x } # 迭代打印出数组中的每个元素

还有很多其他有用的方法诸如:clear, compact!, delete_if, each_index, empty?, fill, flatten!, include?, index, join, pop, push, reverse, reverse_each, rindex, shift, sort, sort!, uniq!, 和 unshift.,我们将在以后的章节进行介绍。

No comments: