经验首页 前端设计 程序设计 Java相关 移动开发 数据库/运维 软件/图像 大数据/云计算 其他经验
当前位置:技术经验 » 程序设计 » Ruby » 查看文章
Ruby数组方法整理
来源:cnblogs  作者:骏马金龙  时间:2019/4/16 8:58:54  对本文有异议

数组方法整理

方法列表:

  • all()、any()、none()和one():测试数组中的所有或部分元素是否满足给定条件。条件可以是语句块中决定,也可以是参数决定
  • append():等价于push()
  • bsearch():二分法查找元素
  • bsearch_index():二分法查找元素并返回索引位置
  • count():计算数组中满足条件的元素个数,length()、size()和不带参数的count()等价
  • collect()和collect!():等价于map
  • combination():对数组元素进行排列操作,see also:permutation()
  • compact()和compact!():移除数组中所有的nil元素
  • cycle():循环迭代整个数组多次
  • delete():删除数组中等于某值的元素,注意原处修改
  • delete_at():删除数组中某索引位置处的元素,类似于slice!(),注意原处修改
  • delete_if():直接从数组中删除满足语句块中条件的元素,将剩下的元素作为数组返回。注意:它是原处修改
  • dig():从嵌套数组中逐层取元素
  • drop():从前向后开始删除n个元素,将剩下的元素作为新数组返回,不是原处修改
  • drop_while():从前向后开始删除元素,直到遇到第一个不满足语句块中条件的元素
  • fetch():获取给定索引处的元素,但可定义索引越界时的处理逻辑
  • fill():替换、修改给定范围的元素
  • filter()和filter!():等价于select()、select!()
  • first():返回数组头部的一个或多个元素
  • flatten()和flatten!():按层次将嵌套数组压平
  • hash:计算数组的hash值,eql?方法比较对象时采用的是hash值比较
  • include?():判断数组中是否存在某元素
  • index()和rindex():搜索数组中某元素的索引位置
  • initialize_copy():使用另一数组中元素替换当前数组元素
  • keep_if():直接从数组中删除不满足语句块中条件的元素,将剩下的元素作为数组返回。即保留满足条件的元素。注意:它是原处修改
  • last():返回数组尾部的一个或多个元素
  • length():返回数组元素个数,length()、size()和不带参数的count()等价
  • map()和map!():迭代数组中每个元素并对它们每一个都执行语句块中的逻辑
  • permutation():对数组元素作组合操作,see also:combination()
  • pop():从数组尾部移除1或多个元素并返回移除的元素
  • prepend():等价于unshift()
  • product():将多个数组的各个元素进行组合
  • push():向数组尾部追加1或多个元素并返回追加后的数组,等价于append()
  • reject()和reject!():根据语句块中的规则筛选数组中不满足条件的元素
  • repeated_combination():看示例
  • repeated_permutation():看示例
  • replace():等价于initialize_copy()
  • reverse()和reverse!():反转数组
  • reverse_each():反向迭代数组
  • rotate()和rotate!():转动数组
  • select()和select!():根据语句块中的规则筛选数组中满足条件的元素,类似于Perl中的grep()
  • simple():从数组中选取一个或n个随机元素
  • shift():移除数组头部的一个或多个元素,并返回移除的元素
  • shuffle()和shuffle!():打乱数组
  • size():返回数组元素个数,length()、size()和不带参数的count()等价
  • sum():将数组各元素相加,不限于数值相加
  • [sort()和sort!()]:对数组进行排序
  • [sort_by()]:
  • take():从前向后开始返回n个元素
  • take_while():从前向后开始返回元素,直到遇到第一个不满足语句块中条件的元素
  • transpose():对多维数组行列转换,类似于zip()的特殊情况
  • uniq()和uniq!():对数组去除重复元素
  • unshift():向数组头部插入1个或多个给定元素并返回插入后的数组
  • zip():合并多数组的元素

map()和map!()

迭代数组中每个元素,并对它们每一个都执行块中的逻辑,并返回新数组。

map()不会修改原始数组对象,map!()会修改原始对象。

map()和collect()等价,同理map!()和collect!()等价。

  1. arr = [1, 2, 3, 4, 5]
  2. new_arr = arr.map{|a| 2*a}
  3. p new_arr1 # [2, 4, 6, 8, 10]
  4. p arr # [1, 2, 3, 4, 5]
  5. new_arr1 = arr.map!{|a| a**2}
  6. p arr # [1, 4, 9, 16, 25]
  7. p new_arr1 # [1, 4, 9, 16, 25]

zip()

  1. arr.zip(arg, ...) new_ary
  2. arr.zip(arg, ...) {|arr| block} nil

将0或多个arg数组和arr数组的元素一一对应地合并起来。合并时,数量以arr的元素数量为准,不足的以nil补足,多余的元素则忽略。

  1. a = [ 4, 5, 6 ]
  2. b = [ 7, 8, 9 ]
  3. [1, 2, 3].zip(a, b) # [[1,4,7],[2,5,8],[3,6,9]]
  4. [1, 2].zip(a, b) # [[1, 4, 7], [2, 5, 8]]
  5. a.zip([1, 2], [8]) # [[4,1,8],[5,2,nil],[6,nil,nil]]

如果使用语句块的方式,那么每次合并后的子数组将传递给语句块中的变量,然后应用语句块的逻辑,但注意它返回的结果为nil。所以,zip()语句块中的block应当是那些能做实际操作的语句,而不是像一种返回值的方式返回操作后的结果,这样会丢弃结果。看下面示例:

  1. a = [ 4, 5, 6 ]
  2. b = [ 7, 8, 9 ]
  3. [1, 2].zip(a, b) # [[1, 4, 7], [2, 5, 8]]
  4. [1, 2].zip(a, b) do |x|
  5. x.reduce(:+) # (1).不合理
  6. end
  7. [1, 2].zip(a, b) do |x|
  8. p x.reduce(:+) # (2).合理
  9. end
  10. sum = 0
  11. [1, 2].zip(a, b) do |x|
  12. sum += x.reduce(:+) # (3).合理
  13. end
  14. p sum

首先,上面zip()两次传递到语句块中的变量分别是[1, 4, 7][2, 5, 8]x.reduce(:+)表示将x容器(此处为数组)中的元素全都相加。所以,第一次迭代语句块时,x.reduce(:+)的结果是1+4+7=12,第二次迭代的结果是2+5+8=15。

但是在(1)中,它仅仅只是相加了,加了之后结果就被丢弃了,它不会作为新数组的元素返回,因为zip()使用语句块时返回的是nil,而不是新数组。

所以,在(2)中,对相加之后的结果加了一个p()动作将其输出,也就是使用了x.reduce的结果,并没有丢弃。

同理,在(3)中,将相加之后的结果加总到sum上,使得最后sum的值被保留,这里也使用了x.reduce的结果,并没有丢弃。


select()和select!()

filter()、filter!()分别等价于select()、select!()。

迭代数组,并从数组中选择那些符合语句块中测试条件的元素,最后组成一个新数组。

select()不会修改原始数组对象,select!()会修改原始对象。

  1. arr = [1, 2, 3, 4, 5, 6]
  2. new_arr = arr.select {|a| a > 3}
  3. p new_arr # [4, 5, 6]
  4. p arr # [1, 2, 3, 4, 5, 6]
  5. new_arr = arr.select! {|a| a > 3}
  6. p new_arr # [4, 5, 6]
  7. p arr # [4, 5, 6]

reject()和reject!()

和select()是相反的行为,从数组中筛选不满足条件的元素。

reject()不会修改原始数组对象,reject!()会修改原始对象。

  1. arr = [1, 2, 3, 4, 5, 6]
  2. new_arr = arr.reject {|a| a > 3}
  3. p new_arr # [1, 2, 3]
  4. p arr # [1, 2, 3, 4, 5, 6]
  5. new_arr = arr.reject! {|a| a > 3}
  6. p new_arr # [1, 2, 3]
  7. p arr # [1, 2, 3]

keep_if()

  1. keep_if {|item| block} ary
  2. keep_if Enumerator

keep_if()从数组中删除不满足语句块中条件的元素,即保留满足条件的元素。

注意原处修改对象

  1. arr = [1, 2, 3, 4, 5, 6]
  2. new_arr = arr.keep_if {|a| a < 4}
  3. p new_arr # [1, 2, 3]
  4. p arr # [1, 2, 3]

uniq()和uniq!()

  1. ary.uniq -> new_ary
  2. ary.uniq {|item| ...} -> new_ary
  3. ary.uniq! -> ary or nil
  4. ary.uniq! {|item| ...} -> ary or nil

对于语句块格式的语法,将迭代每个元素,然后根据语句块中的返回值作为重复值比较的依据。

对于uniq!(),如果没有任何重复元素可以去除,则返回nil,这时原数组不变,这是带有后缀!但不改变原对象的一个特例。其它情况这些方法均返回去重后的数组。

  1. a = [ "a", "a", "b", "b", "c" ]
  2. a.uniq # ["a", "b", "c"], a不变
  3. b = [["student","sam"], ["student","george"], ["teacher","matz"]]
  4. b.uniq {|s| s.first} # [["student","sam"],["teacher","matz"]],b不变
  5. a = [ "a", "a", "b", "b", "c" ]
  6. a.uniq! # ["a", "b", "c"],a已变
  7. b = [ "a", "b", "c" ]
  8. b.uniq! # nil,b不变
  9. c = [["student","sam"], ["student","george"], ["teacher","matz"]]
  10. c.uniq! {|s| s.first} # [["student","sam"],["teacher","matz"]],c已变

compact()和compact!()

  1. compact! new_ary
  2. compact! ary or nil

去除数组中所有nil元素。

带感叹号的方法表示原处修改,如果没有nil元素可去除,则返回nil。

  1. ["a",nil,"b",nil,"c",nil].compact #["a","b","c"]
  2. ["a",nil,"b",nil,"c"].compact! # ["a","b","c"]
  3. ["a","b","c"].compact! # nil



all()、any()、none()和one()

  1. all? [{ |obj| block } ] true or false
  2. all?(pattern) true or false
  3. any? [{ |obj| block } ] true or false
  4. any?(pattern) true or false
  5. none? [{ |obj| block } ] true or false
  6. none?(pattern) true or false
  7. one? [{ |obj| block } ] true or false
  8. one?(pattern) true or false

对于这些方法,均有三种行为:

  • 当使用语句块时,将判断容器中是否所有元素(all)、是否任一元素(any)、是否没有元素(none)、是否有且只有一个元素(one)满足语句块中的条件
  • 当不使用语句块但给定参数时,将使用===的测试符号去判断容器中是否所有元素(all)、是否任一元素(any)、是否没有元素(none)、是否有且只有一个元素(one)满足条件
  • 当不使用语句块且不给定参数时,将判断容器中是否所有元素(all)、是否任一元素(any)、是否没有元素(none)、是否有且只有一个元素(one)为true

需要特别对待的是空数组,虽然空数组自身是一个bool true,但空数组没有元素

  • 对于all(),空数组表示所有元素都为true,因为它根本没元素,所以返回true
  • 对于any(),空数组表示没有元素为true,因为它根本没元素,所以返回false
  • 对于none(),空数组表示没有元素为true,因为它根本没元素,所以返回true
  • 对于one(),空数组没有一个元素为true,因为它根本没元素,所以返回false
  1. # all()
  2. %w[ant bear cat].all? { |word| word.length >= 3 } # true
  3. %w[ant bear cat].all? { |word| word.length >= 4 } # false
  4. %w[ant bear cat].all?(/t/) # false
  5. [1, 2i, 3.14].all?(Numeric) # true
  6. [nil, true, 99].all? # false
  7. [].all? # true
  1. # any()
  2. %w[ant bear cat].any? { |word| word.length >= 3 } # true
  3. %w[ant bear cat].any? { |word| word.length >= 4 } # true
  4. %w[ant bear cat].any?(/d/) # false
  5. [nil, true, 99].any?(Integer) # true
  6. [nil, true, 99].any? # true
  7. [].any? # false
  1. # none()
  2. %w{ant bear cat}.none? {|word| word.length == 5} # true
  3. %w{ant bear cat}.none? {|word| word.length >= 4} # false
  4. %w{ant bear cat}.none?(/d/) # true
  5. [1, 3.14, 42].none?(Float) # false
  6. [].none? # true
  7. [nil].none? # true
  8. [nil, false].none? # true
  9. [nil, false, true].none? # false
  1. # one()
  2. %w{ant bear cat}.one? {|word| word.length == 4} # true
  3. %w{ant bear cat}.one? {|word| word.length > 4} # false
  4. %w{ant bear cat}.one? {|word| word.length < 4} # false
  5. %w{ant bear cat}.one?(/t/) # false
  6. [ nil, true, 99 ].one? # false
  7. [ nil, true, false ].one? # true
  8. [ nil, true, 99 ].one?(Integer) # true
  9. [].one? # false

count()

计算数组中满足条件的元素个数。

  1. count int
  2. count(obj) int
  3. count {|item| block} int
  • 无参数时,计算数组所有元素个数
  • 有参数时,计算数组中等于obj对象的元素个数,使用==进行等值测试
  • 语句块时,迭代数组每个元素,并计算符合语句块条件的元素个数
  1. ary = [1, 2, 4, 2]
  2. ary.count # 4,数组元素个数
  3. ary.count(2) # 2,等于2的元素个数
  4. ary.count {|x| x%2 == 0} # 3,偶元素个数


length()和size()

两者等价,均返回数组元素个数。和不带参数的count()等价。

cycle()

  1. cycle(n=nil) {|obj| block} nil
  2. cycle(n=nil) Enumerator

迭代数组每个元素并调用语句块,然后循环n次整个数组的迭代过程(注意是按整个数组计算次数,而不是对每个元素,所以是先迭代完一次数组,再循环迭代第二次数组,以此类推)。

如果不给参数或参数为nil,则无限循环迭代。

  1. a = ["a", "b", "c"]
  2. a.cycle {|x| puts x} # a,b,c,a,b,c, ... forever
  3. a.cycle(2) {|x| puts x} # a,b,c,a,b,c

delete()

  1. ary.delete(obj) -> item or nil
  2. ary.delete(obj) {block} -> item or result of block

删除数组中所有等于obj的对象,返回最后被删除的元素。如果没有元素可删除,则返回nil。如果使用了语句块,则在无元素可删除的情况下返回语句块的结果而不是nil。相当于语句块提供了默认值来替代nil返回值。

注意原处修改。

  1. a = [ "a", "b", "b", "b", "c" ]
  2. a.delete("b") # "b"
  3. a # ["a", "c"]
  4. a.delete("z") # nil
  5. a.delete("z") {"not found"} # "not found"

delete_at()

  1. delete_at(index) obj or nil

删除数组中指定索引位置处的元素,并返回该元素,如果索引越界则返回nil。

注意原处修改。

  1. a = ["ant", "bat", "cat", "dog"]
  2. a.delete_at(2) # "cat"
  3. a # ["ant", "bat", "dog"]
  4. a.delete_at(99) # nil

delete_if()

  1. delete_if {|item| block} ary
  2. delete_if Enumerator

delete_if()从数组中删除满足语句块中条件的元素。

注意原处修改。

  1. arr = [1, 2, 3, 4, 5, 6]
  2. new_arr = arr.delete_if {|a| a < 4}
  3. p new_arr # [4, 5, 6]
  4. p arr # [4, 5, 6]

dig()

  1. dig(idx, ...) object

根据给定的索引idx去提取数组中的元素。这主要用于从多层嵌套的数组取元素,特别是层次复杂的数组。

  1. a = [[1, [2, 3]]]
  2. a.dig(0, 1, 1) # 3
  3. a.dig(1, 2, 3) # nil
  4. a.dig(0, 0, 0) # TypeError: Integer does not have #dig method
  5. [42, {foo: :bar}].dig(1, :foo) # :bar

其中:

dig(0,1,1)表示首先从数组a中取idx=0的元素,即取得[1,[2,3]],再取得idx=1的元素,即[2,3],最后再取得idx=1的元素,即3。

dig(1,2,3)在第1次取元素的过程越界,因为[[1, [2, 3]]]只有一个元素。

dig(0,0,0)第一次取得[1, [2, 3]],第二次取得1,因为1不再是数组,所以第三次取元素时报错。


first()和last()

  1. first obj or nil
  2. first(n) new_ary
  3. last obj or nil
  4. last(n) new_ary

取数组头部或数组尾部的一个或n个元素,但不修改原数组。

  • 未给定参数时,表示取头或尾的一个元素,数组为空时返回nil
  • 给定参数时,表示取头或尾的n个元素,数组元素不够取时则能取多少返回多少,而数组为空时一个都取不到,所以返回空数组
  1. a = %w(a b c d)
  2. a.first # "a"
  3. a.last # "d"
  4. a.first(2) # ["a", "b"]
  5. a.last(2) # ["c", "d"]
  6. a.first(10) # ["a", "b", "c", "d"]
  7. a.last(10) # ["a", "b", "c", "d"]
  8. [].first # nil
  9. [].first(2) # []


drop()和take()

  1. drop(n) new_ary
  2. take(n) new_ary

take()从数组头部返回前n个元素。

drop()从数组头部删除前n个元素,然后将剩下的元素作为新数组返回。

原数组不变。

  1. # drop()
  2. a = ["a", "b", "c"]
  3. a.drop(2) # 返回["c"],a不变
  4. # take()
  5. a = [1, 2, 3, 4, 5, 0]
  6. a.take(3) # [1, 2, 3]


drop_while()和take_while()

  1. drop_while {|obj| block} new_ary
  2. drop_while Enumerator
  3. take_while {|obj| block} new_ary
  4. take_while Enumerator

take_while()从数组头部开始迭代元素,直到遇到不满组语句块中条件的元素停止迭代,然后返回所有已迭代的满足条件的元素。

drop_while()从数组头部开始迭代元素,一直删除元素直到遇到不满足语句块中条件的元素停止迭代。然后将剩下的元素作为新数组返回。

注意,不是原处修改。

  1. # drop_while()
  2. arr = [1, 2, 3, 4, 5, 6]
  3. new_arr = arr.drop_while {|a| a<4}
  4. p new_arr # [4, 5, 6]
  5. p arr # [1, 2, 3, 4, 5, 6]
  6. # take_while()
  7. a = [1, 2, 3, 4, 5, 0]
  8. a.take_while {|i| i < 3} #=> [1, 2]

fetch()

  1. fetch(index) obj
  2. fetch(index, default) obj
  3. fetch(index) {|index| block} obj

按照给定index获取数组中的元素。如果index越界,则根据三种不同形式进行处理:

  • 没有给第二个参数、没有使用语句块时,直接报错
  • 给了第二个参数时,index越界时将返回该第二个参数值作为默认值
  • 使用了语句块时,index越界时将执行语句块中内容,并将index传递给语句块变量
  1. a = [ 11, 22, 33, 44 ]
  2. a.fetch(1) #=> 22
  3. a.fetch(-1) #=> 44
  4. a.fetch(4, 'cat') #=> "cat"
  5. a.fetch(100) {|i| puts "#{i} is out of bounds"}
  6. #=> "100 is out of bounds"

fill()

  1. # 原处修改
  2. fill(obj) ary
  3. fill(obj, start [, length]) ary
  4. fill(obj, range) ary
  5. fill {|index| block} ary
  6. fill(start [, length]) {|index| block} ary
  7. fill(range) {|index| block} ary

前三种形式,据使用obj值替换数组中给定范围内元素的值:

  • fill(obj):使用obj替换所有元素
  • fill(obj, start [, len]):替换从start开始,长度len个元素,没有给len则替换后面所有元素
  • fill(obj, range):替换range所指定的范围元素

后三种形式,将传递数组索引到语句块,且给定范围内的元素将使用语句块的计算结果进行替换,范围之外的则保留使用索引值元素。

  1. a = [ "a", "b", "c", "d" ]
  2. a.fill("x") # ["x", "x", "x", "x"]
  3. a.fill("z", 2) # ["x", "x", "z", "z"]
  4. a.fill("y", 0..1) # ["y", "y", "z", "z"]
  5. a.fill {|i| i*i} # [0, 1, 4, 9]
  6. a.fill(-2) {|i| i*i*i} # [0, 1, 8, 27]



pop()、push()和append()

  1. push(obj, ...) ary
  2. append(obj, ...) ary
  3. pop obj or nil
  4. pop(n) new_ary

注意原处修改。

  • push():将给定一个或多个元素追加到数组尾部,因为返回数组自身,所以可以链式追加
  • append():等价于push()
  • pop():从数组尾部移除并返回1个或n个元素(此时作为数组返回),如果数组为空则返回nil。等价于slice!(-n,n)
  1. # push()、append()
  2. a = [ "a", "b", "c" ]
  3. a.push("d","e","f") # %w[a b c d e f]
  4. [1,2,3].push(4).push(5) # [1,2,3,4,5]
  1. # pop()
  2. a = [ "a", "b", "c", "d" ]
  3. a.pop # "d"
  4. a.pop(2) # ["b", "c"]
  5. a # ["a"]



shift()、unshift()和prepend()

  1. unshift(obj, ...) ary
  2. prepend(obj, ...) ary
  3. shift obj or nil
  4. shift(n) new_ary

注意原处修改。

  • unshift():向数组头部插入一个或多个元素,会导致整个数组原有元素后移
  • prepend():等价于unshift()
  • shift():从数组头部移除并返回1个或n个元素(此时以数组方式返回),会导致整个数组原有元素前移。如果数组为空则返回nil。等价于slice!(0,n)
  1. # unshift、prepend()
  2. a = [ "b", "c", "d" ]
  3. a.unshift("a") #=> ["a", "b", "c", "d"]
  4. a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]
  1. # shift
  2. args = ["-m", "-q", "filename"]
  3. args.shift # "-m"
  4. args # ["-q", "filename"]
  5. args = [ "-m", "-q", "filename" ]
  6. args.shift(2) #=> ["-m", "-q"]
  7. args #=> ["filename"]

flatten()和flatten!()

  1. flatten new_ary
  2. flatten(level) new_ary
  3. flatten! ary or nil
  4. flatten!(level) ary or nil

将多层次的嵌套数组压平,level可以指定最多压到那一层。对于带感叹号后缀的方法,如果数组无法再压或层数不够,则返回nil。

  1. s = [ 1, 2, 3 ] # [1,2,3]
  2. t = [ 4, 5, 6, [7, 8] ] # [4,5,6,[7,8]]
  3. a = [ s, t, 9, 10 ] # [[1,2,3],[4,5,6,[7,8]],9,10]
  4. a.flatten # [1,2,3,4,5,6,7,8,9,10]
  5. a = [ 1, 2, [3, [4, 5] ] ]
  6. a.flatten(1) # [1, 2, 3, [4, 5]]
  7. a = [ 1, 2, [3, [4, 5] ] ]
  8. a.flatten! #=> [1, 2, 3, 4, 5]
  9. a.flatten! #=> nil,已经压平了
  10. a #=> [1, 2, 3, 4, 5]
  11. a = [ 1, 2, [3, [4, 5] ] ]
  12. a.flatten!(1) #=> [1, 2, 3, [4, 5]]
  13. a.flatten!(1) #=> [1, 2, 3, 4, 5]
  14. a.flatten!(1) #=> nil

hash()

计算数组的hash值。执行eql?()的比较时,其比较依据就是hash值。

  1. [1, 2].hash # 2027605168499122706
  2. [1, 2.0].hash # 3393919734812826294

include?()

  1. include?(object) true or false

判断数组中是否包含某元素。判断的依据是使用==比较。

  1. a = [ "a", "b", "c" ]
  2. a.include?("b") # true
  3. a.include?("z") # false
  4. [1, 2.0].include?(2) # true

index()和rindex()

  1. index(obj) int or nil
  2. index {|item| block} int or nil
  3. index Enumerator
  4. rindex(obj) int or nil
  5. rindex {|item| block} int or nil
  6. rindex Enumerator

搜索数组中满足条件的元素并返回其索引位置,搜索不到将返回nil。

  1. # index(obj)、rindex(obj)
  2. # 返回数组中第一个、最后一个等于obj的元素位置
  3. # 使用"=="进行测试
  4. a = [ "a", "b", "c" ]
  5. p a.index("b") # 1
  6. p a.index("z") # nil
  7. p a.index {|x| x == "b"} # 1
  8. # (r)index {|item| block}
  9. # 返回第一个/最后一个满足语句块中条件的元素位置
  10. a = [ "a", "b", "b", "b", "c" ]
  11. p a.rindex("b") # 3
  12. p a.rindex("z") # nil
  13. p a.rindex {|x| x == "b"} # 3


initialize_copy()和replace()

两者等价。

  1. initialize_copy(other_ary) ary

使用other_ary数组替换当前数组中的元素,并按需收缩、扩展。

注意原处修改。

  1. a = %w(a b c d e) # ["a", "b", "c", "d", "e"]
  2. a.replace(%w[x y z]) # ["x", "y", "z"]
  3. a # ["x", "y", "z"]

join()

  1. join(separator=$,) str

将数组各元素通过连接符连接起来,转换成字符串返回。

不给sep时默认以$,作为连接符,如果$,为nil(默认就是nil),则默认使用空字符进行连接。

嵌套数组会递归连接。

连接符必须是字符串类型。

实际上,join()的过程是:将数组各元素全都使用to_s转换成字符串,然后对连接符使用to_str转换成字符串。

  1. ["a","b","c"].join # "abc"
  2. ["a","b","c"].join("-") # "a-b-c"
  3. ["a",[1,2,[:x,:y]], "b" ].join("-") # "a-1-2-x-y-b"
  4. # 数值不能作为连接符,因为它没有定义to_str
  5. %w(perl shell ruby).join(1) # TypeError


max()和min()

  1. max obj
  2. max {|a, b| block} obj
  3. max(n) array
  4. max(n) {|a, b| block} array
  5. min obj
  6. min {|a, b| block} obj
  7. min(n) array
  8. min(n) {|a, b| block} array

无参数、无语句块的形式,表示从数组中返回最大/最小的元素。何为最大/最小,只有数组中所有元素都实现了Comparable模块才允许比较,也就是能使用<=>对数组不同元素之间进行比较。

带语句块形式的形式,表示将每个元素传递到语句块之后经过一番处理,然后通过<=>比较得到返回结果。

带参数的形式则表示以数组的方式返回最大/最小的n个元素,也就是返回前几名对象。

  1. ary = %w(albatross dog horse)
  2. ary.max # "horse"
  3. ary.max {|a, b| a.length <=> b.length} # "albatross"
  4. ary.max {|a, b| b.length <=> a.length} # "dog"
  5. ary = %w[albatross dog horse]
  6. ary.max(2) # ["horse", "dog"]
  7. ary.max(2){|a, b| a.length <=> b.length} # ["albatross","horse"]
  1. ary = %w(albatross dog horse)
  2. a = ary.max do |a, b|
  3. x=a.length
  4. y=b.length
  5. y <=> x
  6. end


permutation()和combination()

  1. permutation {|p| block} ary
  2. permutation Enumerator
  3. permutation(n) {|p| block} ary
  4. permutation(n) Enumerator
  5. combination(n) {|c| block} ary
  6. combination(n) Enumerator

permutation()对数组的元素进行排列,返回排列后的各数组。

  • 当指定参数n时,则对所有n个元素作排列
  • 当不指定参数n时,则n默认为数组长度,即对所有元素作排列

combination()对数组作n个元素的组合。

注意,排列、组合的顺序不作任何保证。

关于排列和组合的区别:

  • 排列:从n个不同的元素中,取r个不重复的元素,按次序排列,称为从n个中取r个的无重复排列
  • 组合:从n个不同的元素中,取r个不重复的元素,组成一个子集,而不考虑其元素的顺序,称为从n个中取r个的无重组和

看下面的示例即可理解:

  1. # permutation()作排列操作
  2. a = [1, 2, 3]
  3. a.permutation.to_a # [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
  4. a.permutation(1).to_a # [[1],[2],[3]]
  5. a.permutation(2).to_a # [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
  6. a.permutation(3).to_a # [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
  7. a.permutation(0).to_a # [[]] # one permutation of length 0
  8. a.permutation(4).to_a # [] # no permutations of length 4
  1. # combination()作组合操作
  2. a = [1, 2, 3, 4]
  3. a.combination(1).to_a # [[1],[2],[3],[4]]
  4. a.combination(2).to_a # [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
  5. a.combination(3).to_a # [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
  6. a.combination(4).to_a # [[1,2,3,4]]
  7. a.combination(0).to_a # [[]] # one combination of length 0
  8. a.combination(5).to_a # [] # no combinations of length 5

当使用了语句块时,每个排列后的子数组将传递给语句块的变量。

  1. a = [1, 2, 3, 4]
  2. a.combination(3) {|x| p x << "z" }
  3. ## 输出:
  4. ## [1, 2, 3, "z"]
  5. ## [1, 2, 4, "z"]
  6. ## [1, 3, 4, "z"]
  7. ## [2, 3, 4, "z"]


repeated_combination()和repeated_permutation()

  1. repeated_combination(n) {|c| block} ary
  2. repeated_combination(n) Enumerator
  3. repeated_permutation(n) {|p| block} ary
  4. repeated_permutation(n) Enumerator

重复n个数组自身,并对这n个数组进行排列操作、组合操作。看示例即可明白。

  1. # repeated_combination()
  2. a = [1, 2, 3]
  3. a.repeated_combination(1).to_a # [[1], [2], [3]]
  4. a.repeated_combination(2).to_a # [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
  5. a.repeated_combination(3).to_a # [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
  6. # [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
  7. a.repeated_combination(4).to_a # [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
  8. # [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
  9. # [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
  10. a.repeated_combination(0).to_a # [[]] # one combination of length 0
  1. # repeated_permutation()
  2. a = [1, 2]
  3. a.repeated_permutation(1).to_a # [[1], [2]]
  4. a.repeated_permutation(2).to_a # [[1,1],[1,2],[2,1],[2,2]]
  5. a.repeated_permutation(3).to_a # [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
  6. # [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
  7. a.repeated_permutation(0).to_a # [[]] # one permutation of length 0

product()

  1. product(other_ary, ...) new_ary
  2. product(other_ary, ...) {|p| block} ary

将数组和other_ary的各元素进行组合后返回。

如果使用了语句块,则每个组合后的子数组都传递给语句块,并返回数组自身(即a.product() {}时返回a)。

  1. [1,2,3].product([4,5]) # [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
  2. [1,2].product([1,2]) # [[1,1],[1,2],[2,1],[2,2]]
  3. [1,2].product([3,4],[5,6]) # [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
  4. # [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
  5. [1,2].product() # [[1],[2]]
  6. [1,2].product([]) # []
  1. # 使用语句块形式
  2. a = [1,2,3]
  3. sub_a = a.product([4,5]) {|x| p x}
  4. p sub_a
  5. ## 输出:
  6. =begin
  7. [1, 4]
  8. [1, 5]
  9. [2, 4]
  10. [2, 5]
  11. [3, 4]
  12. [3, 5]
  13. [1, 2, 3]
  14. =end

rotate()和rotate!()

  1. rotate(count=1) new_ary
  2. rotate!(count=1) ary

转动数组,使得count位置处的元素作为新数组的第一个元素。带感叹号表示原处修改。

  1. a = [ "a", "b", "c", "d" ]
  2. a.rotate # ["b", "c", "d", "a"]
  3. a # ["a", "b", "c", "d"]
  4. a.rotate(2) # ["c", "d", "a", "b"]
  5. a.rotate(-3) # ["b", "c", "d", "a"]
  6. a = [ "a", "b", "c", "d" ]
  7. a.rotate! # ["b", "c", "d", "a"]
  8. a # ["b", "c", "d", "a"]
  9. a.rotate!(2) # ["d", "a", "b", "c"]
  10. a.rotate!(-3) # ["a", "b", "c", "d"]

transpos()

  1. transpose new_ary

如果是多维数组,则返回行列转换后的新数组。如果元素个数不一致,则直接报错。

  1. a = [[1,2], [3,4], [5,6]]
  2. a.transpose # [[1, 3, 5], [2, 4, 6]]
  3. [[1,2,3],[3,4],[5,6]].transpose # IndexError

simple()

  1. sample obj
  2. sample(random: rng) obj
  3. sample(n) new_ary
  4. sample(n, random: rng) new_ary

从数组中随机选择一个或n个元素。选择随机元素的方式是使用随机的索引进行选取。如果选择多个随机元素,则选择随机元素的索引位置会保证唯一性,但仍然可能会选中重复元素,因为数组自身可能会包含重复元素。

参数rng表示指定生成索引随机数的生成器。

当为空数组时,第一种形式返回nil,第二种形式返回空数组。

  1. a = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  2. a.sample # 7
  3. a.sample(4) # [6, 4, 2, 5]
  1. a.sample(random: Random.new(1)) # 6
  2. a.sample(4, random: Random.new(1)) # [6, 10, 9, 2]

shuffle()和shuffle!()

  1. shuffle new_ary
  2. shuffle(random: rng) new_ary
  3. shuffle! ary
  4. shuffle!(random: rng) ary

打乱数组元素并返回。感叹号后缀表示原处修改。

rng参数指定生成随机数的生尘器。

  1. # shuffle()
  2. a = [ 1, 2, 3 ] # [1, 2, 3]
  3. a.shuffle # [2, 3, 1]
  4. a # [1, 2, 3]
  5. a.shuffle(random: Random.new(1)) # [1, 3, 2]
  6. # shuffle!()
  7. a = [ 1, 2, 3 ] # [1, 2, 3]
  8. a.shuffle! # [2, 3, 1]
  9. a # [2, 3, 1]
  10. a.shuffle!(random: Random.new(1)) # [1, 3, 2]

sum()

  1. sum(init=0) number
  2. sum(init=0) {|e| expr } number

返回各元素加法操作之和。例如[e1, e2, e3].sum返回init + e1 + e2 + e3

如果使用了语句块,则在相加之前,先对各元素执行语句块。

如果数组为空,则返回init参数值。

  1. [].sum # 0
  2. [].sum(0.0) # 0.0
  3. [1, 2, 3].sum # 6
  4. [3, 5.5].sum # 8.5
  5. [2.5, 3.0].sum(0.0) {|e| e * e } # 15.25
  6. [Object.new].sum # TypeError

不仅限于可以执行数值相加操作,只要通过init参数显式指明初始值类型即可:

  1. ["a", "b", "c"].sum("") # "abc"
  2. [[1], [[2]], [3]].sum([]) # [1, [2], 3]

但是,join()flatten()都比上述方式运行的更快。

  1. ["a", "b", "c"].join # "abc"
  2. [[1], [[2]], [3]].flatten(1) # [1, [2], 3]

reverse()和reverse!()

  1. reverse new_ary
  2. reverse! ary

将数组元素反转。带感叹号表示原处反转。

  1. # reverse()
  2. ["a","b","c"].reverse # ["c","b", a"]
  3. [1].reverse # [1]
  4. # reverse!()
  5. a = ["a","b","c"]
  6. a.reverse! # ["c","b","a"]
  7. a # ["c","b","a"]

reverse_each()

  1. reverse_each {|item| block} ary
  2. reverse_each Enumerator

类似于each(),但反向迭代,即从数组尾部开始迭代。

  1. a = [ "a", "b", "c" ]
  2. a.reverse_each {|x| print x," "} # 输出c b a

sort()和sort!()

  1. sort new_ary
  2. sort {|a, b| block} new_ary
  3. sort! ary
  4. sort! {|a, b| block} ary

对数组元素进行排序,然后返回。带感叹号后缀表示原处修改。

当没有使用语句块时,排序依据是对各元素使用<=>进行比较。

当使用了语句块时,将根据语句块中指定的依据进行排序。

当两元素比较是等值的,那么将无法保证谁在前、谁在后。

  1. # sort()
  2. ary = [ "d", "a", "e", "c", "b" ]
  3. ary.sort # ["a","b","c","d","e"]
  4. ary.sort {|a, b| a <=> b} # ["a","b","c","d","e"]
  5. ary.sort {|a, b| b <=> a} # ["e","d","c","b","a"]
  6. # sort!()
  7. ary = [ "d", "a", "e", "c", "b" ]
  8. ary.sort! # ["a","b","c","d","e"]
  9. ary.sort! {|a, b| a <=> b} # ["a","b","c","d","e"]
  10. ary.sort! {|a, b| b <=> a} # ["e","d","c","b","a"]

sort_by()和sort_by!()

sort_by()取自mix-in的Enumerable。sort_by!()是Array自身所实现的。

  1. sort_by { |obj| block } array
  2. sort_by an_enumerator
  3. sort_by! {|obj| block} ary
  4. sort_by! Enumerator

按照语句块中的规则进行排序。默认升序排序。

  1. a = %w(perl shell php python java ruby)
  2. a.sort_by {|a| a.length}
  3. #=> %w[php java ruby perl shell python]
  4. (a.sort_by {|a| a[-1]}).reverse
  5. #=> %w[ruby php python perl shell java]

第一个排序语句是按照各元素的长度进行升序排序。

第二个排序语句是按照各元素最后一个字符进行升序排序,然后反转排序结果。


bsearch()和bserach_index()

  1. bsearch {|x| block } elem
  2. bsearch_index {|x| block } int or nil

两者工作机制完全一致,均用于二分法查找元素,唯一不同的在于返回结果。前者返回容器元素,后者返回对应索引。

二分法算法查找过程略。但对于这里的两个方法,很有必要解释一番。仅以bsearch()方法用法为例。

首先要求数组是已排序过的,或者说对于语句块来说是单调的

bsearch()一般有两种用法:查找单个最小元素(find-minimum)、查找范围内元素(find-any)。

find-minimum(即查找单个元素时),要求语句块返回true/false。当返回true,则向左继续,当返回false,则向右继续。直到没有元素,才返回最后一个true元素,或一直都没有true则返回nil

find-any(即查找范围元素时),要求语句块返回负数、正数、0。当返回正数时,向右继续,当返回负数时,向左继续,返回0则停止

find-minimum示例1:不等值判断

  1. a = [-1, 1, 2, 4, 5]
  2. p a.bsearch {|x| x > 2} # 4

此语句中,语句块首先从数组中取中间的元素(如果是偶数,比如6个元素,则取第4个元素),此处所取元素值为2。

将其进行x>2的判断,返回false,于是向右继续得到子数组[4, 5]。再从中取得中间元素5,5大于2返回true。于是向左继续,取得元素4,4大于2返回true。没法继续向左,所以返回最后一次为true的元素,即4。

再自行考虑与小于2(如0)、大于2(如3)的值比较时,整个过程是如何的?

find-minimum示例2:等值判断

  1. arr_in = [-1, 1, 2, 4, 5]
  2. p arr_in.bsearch { |x| x == -1 } # nil
  3. p arr_in.bsearch { |x| x == 1 } # nil
  4. p arr_in.bsearch { |x| x == 2 } # 2
  5. p arr_in.bsearch { |x| x == 4 } # nil
  6. p arr_in.bsearch { |x| x == 5 } # 5

为什么和数组中的元素比较,有些能返回值,有些却返回nil?

对于x == -1x == 1x == 4的比较。首先取中间元素2,比较结果为false,于是向右得到子数组[4, 5],从中取中间元素5,结果为false,继续往右,但是没有元素可以往右了,而且之前一直没有true的结果,所以返回nil。

同理对于x == 2的比较。首先取中间元素2,比较结果为true,于是向左得到子数组[-1,1],取中间元素1,比较结果为false,于是向右,但没有元素了,于是返回最后一次的true,即元素2。

对于x == 5的比较,首先取中间元素2,比较结果为false,于是向右得到子数组[4, 5],从中取中间元素5,结果为true,继续往左,得到子数组[4],于是中间元素4与之比较为false,继续向右,但向右已没有元素,于是返回最后一次为true的元素,即5。

find-any示例3:返回正、负、0的表达式

  1. a = [-1, 1, 2, 4, 5]
  2. a.bsearch {|x| -1 - x} # -1
  3. a.bsearch {|x| 1 - x} # 1
  4. a.bsearch {|x| 2 - x} # 2
  5. a.bsearch {|x| 4 - x} # 4
  6. a.bsearch {|x| 5 - x} # 5
  7. a.bsearch {|x| 3 - x} # nil

对于-1 - x1 - x,首先取中间元素2,返回结果负数,于是向左继续,得到子数组[-1, 1],取中间元素1,对于1 - x返回0,于是立即停止并返回,对于-1 - x返回-2继续向左得到[-1],取中间元素相减后返回0,于是立即停止并返回-1。

对于2-x,首先取中间元素2,返回结果0,立即停止并返回2。

对于4-x5-x,首先取中间元素2,返回结果为正数,所以向右继续取得子数组[4, 5],取中间元素5,对于5-x立即停止并返回,对于4-x得到负数于是向左取得子数组[4],最后返回0并停止。

而对于3 - x,则首先返回1为正数,向右取子数组[4, 5],再次返回负数,于是向左取得[4],仍然为负数,但已无元素可继续向左,于是返回nil。

find-any示例4:<=>符号的比较

当在bsearch()中使用<=>符号时,必须将待比较值放在左边,因为<=>的操作符两边元素的顺序很重要。

  1. a = [-1, 1, 2, 4, 5]
  2. # 待比较值放左边,参数放右边
  3. a.bsearch {|x| -1 <=> x} # -1
  4. a.bsearch {|x| 1 <=> x} # 1
  5. a.bsearch {|x| 2 <=> x} # 2
  6. a.bsearch {|x| 4 <=> x} # 4
  7. a.bsearch {|x| 5 <=> x} # 5
  8. a.bsearch {|x| 3 <=> x} # nil
  9. # 待比较值放右边,参数放左边
  10. a.bsearch {|x| x <=> -1} # nil
  11. a.bsearch {|x| x <=> 1} # nil
  12. a.bsearch {|x| x <=> 2} # 2
  13. a.bsearch {|x| x <=> 4} # nil
  14. a.bsearch {|x| x <=> 5} # nil

首先分析待比较值放左边,参数放右边的情况。

对于-1 <=> x1 <=> x,首先取中间元素2,比较的返回结果为-1,于是向左继续取得子数组[-1, 1],继续取中间元素1,对于1 <=> x所比较的返回结果0,于是立即停止并返回元素1。对于-1 <=> x比较的返回结果-1,于是向左继续取自数组[-1],最终比较的返回结果为0,返回-1元素。

对于2 <=> x,第一次取中间元素2就得到0,立即停止并返回。

对于4 <=> x5 <=> x,首先取中间元素2,比较的返回结果为1,于是向右继续取得子数组[4, 5],继续取中间元素5,对于5 <=> x所比较的返回结果0,于是立即停止并返回元素51。对于4 <=> x比较的返回结果-1,于是向左继续取自数组[4],最终比较的返回结果为0,返回4元素。

对于3 <=> x,自行分析。

再分析待比较值放右边,参数放右边的情况。

对于x <=> -1x <=> 1,首先取中间元素2,比较的返回结果为1,于是向右继续取得子数组[4, 5],到这已经不用再向后分析了,因为它们都大于待比价的值,使得一直向右取子数组,最终导致返回nil。

对于x <=> 2,第一次取中间元素2就得到0,立即停止并返回。

对于x <=> 4x <=> 5,首先取中间元素2,比较的返回结果为-1,于是向右继续取得子数组[-1, 1],到这已经不用再向后分析了,因为它们都小于于待比价的值,使得一直向左取子数组,最终导致返回nil。

原文链接:http://www.cnblogs.com/f-ck-need-u/p/10709633.html

 友情链接:直通硅谷  点职佳  北美留学生论坛

本站QQ群:前端 618073944 | Java 606181507 | Python 626812652 | C/C++ 612253063 | 微信 634508462 | 苹果 692586424 | C#/.net 182808419 | PHP 305140648 | 运维 608723728

W3xue 的所有内容仅供测试,对任何法律问题及风险不承担任何责任。通过使用本站内容随之而来的风险与本站无关。
关于我们  |  意见建议  |  捐助我们  |  报错有奖  |  广告合作、友情链接(目前9元/月)请联系QQ:27243702 沸活量
皖ICP备17017327号-2 皖公网安备34020702000426号