Ruby 2.4

Array

Array类

父类:ObjectIncluded 模块:Enumerable

数组是有序的,任何对象的整数索引集合。

数组索引从0开始,如在C或Java中。负数索引被假定为相对于数组末尾—也就是说,-1的索引表示数组的最后一个元素,-2是数组中最后一个元素的下一个元素,依此类推。

创建数组

可以通过使用文字构造函数[]来创建一个新的数组。数组可以包含不同类型的对象。例如,下面的数组包含一个整数,一个字符串和一个浮点数:

ary = [1, "two", 3.0] #=> [1, "two", 3.0]

也可以通过显式调用:: new来创建一个数组,其中包括零,一个(Array的初始大小)或两个参数(初始大小和一个默认对象)。

ary = Array.new #=> [] Array.new(3) #=> [nil, nil, nil] Array.new(3, true) #=> [true, true, true]

请注意,第二个参数使用对同一对象的引用来填充数组。因此,仅当您需要使用本地不可变对象(例如符号,数字,真或假)实例化数组时才推荐使用它。

要创建一个包含单独对象的数组,可以改为传递一个块。该方法可以安全地用于可变对象,例如哈希,字符串或其他数组:

Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]

这也是构建多维数组的一种快速方法:

empty_table = Array.new(3) { Array.new(3) } #=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

也可以使用由Kernel提供的Array()方法创建数组,该方法尝试调用to_ary,然后使用to_a参数。

Array{:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]

使用示例

除了通过Enumerable模块混入的方法外,Array类还具有用于访问,搜索和操作数组的专有方法。

下面列出了一些比较常见的部分。

访问元素

可以使用#[]方法检索数组中的元素。它可以采用单个整数参数(数字索引),一对参数(开始和长度)或范围。负指数从最后开始计数,-1是最后一个元素。

arr = [1, 2, 3, 4, 5, 6] arr[2] #=> 3 arr[100] #=> nil arr[-3] #=> 4 arr[2, 3] #=> [3, 4, 5] arr[1..4] #=> [2, 3, 4, 5] arr[1..-3] #=> [2, 3, 4]

访问特定数组元素的另一种方法是使用at方法

arr.at(0) #=> 1

切片方法以与#[]相同的方式工作。

要为数组边界之外的索引产生错误,或者在发生这种情况时提供默认值,可以使用fetch。

arr = ['a', 'b', 'c', 'd', 'e', 'f'] arr.fetch(100) #=> IndexError: index 100 outside of array bounds: -6...6 arr.fetch(100, "oops") #=> "oops"

首先和最后的特殊方法将分别返回数组的第一个和最后一个元素。

arr.first #=> 1 arr.last #=> 6

要返回数组的第一个n元素,请使用take

arr.take(3) #=> [1, 2, 3]

通过在n元素被删除后返回元素,drop与之相反:

arr.drop(3) #=> [4, 5, 6]

获取有关数组的信息

数组始终跟踪自己的长度。要查询数组中包含的元素数量,请使用length,count或size。

browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE'] browsers.length #=> 5 browsers.count #=> 5

检查数组是否包含任何元素

browsers.empty? #=> false

检查数组中是否包含特定项目

browsers.include?('Konqueror') #=> false

将项目添加到数组

可以使用push或<<将项目添加到数组的末尾

arr = [1, 2, 3, 4] arr.push(5) #=> [1, 2, 3, 4, 5] arr << 6 #=> [1, 2, 3, 4, 5, 6]

unshift将添加一个新的项目到数组的开头。

arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]

通过插入,您可以在任何位置向阵列添加新元素。

arr.insert(3, 'apple') #=> [0, 1, 2, 'apple', 3, 4, 5, 6]

使用插入方法,您也可以一次插入多个值:

arr.insert(3, 'orange', 'pear', 'grapefruit') #=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]

从阵列中删除项目

弹出方法删除数组中的最后一个元素并返回它:

arr = [1, 2, 3, 4, 5, 6] arr.pop #=> 6 arr #=> [1, 2, 3, 4, 5]

要检索并同时删除第一个项目,请使用shift:

arr.shift #=> 1 arr #=> [2, 3, 4, 5]

删除特定索引处的元素:

arr.delete_at(2) #=> 4 arr #=> [2, 3, 5]

要删除数组中任何位置的特定元素,请使用delete:

arr = [1, 2, 2, 3] arr.delete(2) #=> 2 arr #=> [1,3]

如果您需要nil从数组中删除值,一个有用的方法是紧凑的:

arr = ['foo', 0, nil, 'bar', 7, 'baz', nil] arr.compact #=> ['foo', 0, 'bar', 7, 'baz'] arr #=> ['foo', 0, nil, 'bar', 7, 'baz', nil] arr.compact! #=> ['foo', 0, 'bar', 7, 'baz'] arr #=> ['foo', 0, 'bar', 7, 'baz']

另一个常见需求是从数组中删除重复的元素。

它具有非破坏性的uniq和破坏性的uniq!

arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556] arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]

迭代数组

像包含Enumerable模块的所有类一样,Array具有每个方法,它定义应该迭代哪些元素以及如何进行迭代。如果是Array,则Array实例中的所有元素将按顺序屈服到所提供的块。

请注意,此操作会使阵列保持不变。

arr = [1, 2, 3, 4, 5] arr.each { |a| print a -= 10, " " } # prints: -9 -8 -7 -6 -5 #=> [1, 2, 3, 4, 5]

另一个有用的迭代器是reverse_each,它将以相反的顺序迭代数组中的元素。

words = %w[first second third fourth fifth sixth] str = "" words.reverse_each { |word| str += "#{word} " } p str #=> "sixth fifth fourth third second first "

map方法可以用来创建一个基于原始数组的新数组,但是通过提供的块修改值:

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

从数组中选择项目

元素可以根据块中定义的标准从数组中选择。选择可以以破坏性或非破坏性的方式发生。尽管破坏性操作会修改它们被调用的数组,但非破坏性方法通常会返回一个包含所选元素的新数组,但保留原始数组不变。

无损选择

arr = [1, 2, 3, 4, 5, 6] arr.select { |a| a > 3 } #=> [4, 5, 6] arr.reject { |a| a < 3 } #=> [3, 4, 5, 6] arr.drop_while { |a| a < 4 } #=> [4, 5, 6] arr #=> [1, 2, 3, 4, 5, 6]

破坏性选择

选择!并拒绝!是相应的破坏性选择和拒绝方法

与select和reject类似,delete_if和keep_if在提供相同的块时具有完全相反的结果:

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

公共类方法

显示来源

返回填充给定对象的新数组。

Array.[]( 1, 'a', /^A/ ) # => [1, "a", /^A/] Array[ 1, 'a', /^A/ ] # => [1, "a", /^A/] [ 1, 'a', /^A/ ] # => [1, "a", /^A/]

static VALUE rb_ary_s_create(int argc, VALUE *argv, VALUE klass) { VALUE ary = ary_new(klass, argc if (argc > 0 && argv) { ary_memcpy(ary, 0, argc, argv ARY_SET_LEN(ary, argc } return ary; }

new(size=0, default=nil) 显示源

new(array)

new(size) {|index| block }

Returns a new array.

在第一种形式中,如果没有参数被发送,新的数组将是空的。当发送一个size和一个可选项时default,将创建一个数组,其size副本为default。注意所有的元素都会引用同一个对象default

第二种形式创建一个作为参数传递的数组副本(该数组通过在参数上调用#to_ary生成)。

first_array = ["Matz", "Guido"] second_array = Array.new(first_array) #=> ["Matz", "Guido"] first_array.equal? second_array #=> false

在最后一种形式中,创建给定大小的数组。该数组中的每个元素都是通过将元素的索引传递给给定的块并存储返回值来创建的。

Array.new(3){ |index| index ** 2 } # => [0, 1, 4]

常见的陷阱

发送第二个参数时,将使用相同的对象作为所有数组元素的值:

a = Array.new(2, Hash.new) # => [{}, {}] a[0]['cat'] = 'feline' a # => [{"cat"=>"feline"}, {"cat"=>"feline"}] a[1]['cat'] = 'Felix' a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]

由于所有数组元素都存储相同的散列,因此对其中一个散列的更改将影响它们全部。

如果您需要多个副本,则应使用块版本,该版本每次需要初始化数组的元素时都使用该块的结果:

a = Array.new(2) { Hash.new } a[0]['cat'] = 'feline' a # => [{"cat"=>"feline"}, {}]

static VALUE rb_ary_initialize(int argc, VALUE *argv, VALUE ary) { long len; VALUE size, val; rb_ary_modify(ary if (argc == 0) { if (ARY_OWNS_HEAP_P(ary) && RARRAY_CONST_PTR(ary) != 0) { ruby_sized_xfree((void *)RARRAY_CONST_PTR(ary), ARY_HEAP_SIZE(ary) } rb_ary_unshare_safe(ary FL_SET_EMBED(ary ARY_SET_EMBED_LEN(ary, 0 if (rb_block_given_p()) { rb_warning("given block not used" } return ary; } rb_scan_args(argc, argv, "02", &size, &val if (argc == 1 && !FIXNUM_P(size)) { val = rb_check_array_type(size if (!NIL_P(val)) { rb_ary_replace(ary, val return ary; } } len = NUM2LONG(size /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */ if (len < 0) { rb_raise(rb_eArgError, "negative array size" } if (len > ARY_MAX_SIZE) { rb_raise(rb_eArgError, "array size too big" } /* recheck after argument conversion */ rb_ary_modify(ary ary_resize_capa(ary, len if (rb_block_given_p()) { long i; if (argc == 2) { rb_warn("block supersedes default value argument" } for (i=0; i<len; i++) { rb_ary_store(ary, i, rb_yield(LONG2NUM(i)) ARY_SET_LEN(ary, i + 1 } } else { ary_memfill(ary, 0, len, val ARY_SET_LEN(ary, len } return ary; }

try_convert(obj) → array or nil Show source

尝试使用to_ary方法将obj转换为数组。 返回转换后的数组,如果obj因任何原因无法转换,则返回nil。 此方法可用于检查参数是否为数组。

Array.try_convert([1]) #=> [1] Array.try_convert("1") #=> nil if tmp = Array.try_convert(arg) # the argument is an array elsif tmp = String.try_convert(arg) # the argument is a string end

static VALUE rb_ary_s_try_convert(VALUE dummy, VALUE ary) { return rb_check_array_type(ary }

公共实例方法

ary & other_ary → new_ary Show source

Set Intersection - 返回一个包含两个数组通用的唯一元素的新数组。订单从原始数组中保留。

它使用hash和eql比较元素?提高效率的方法。

[ 1, 1, 3, 5 ] & [ 3, 2, 1 ] #=> [ 1, 3 ] [ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ] #=> [ 'a', 'b' ]

另见#uniq。

static VALUE rb_ary_and(VALUE ary1, VALUE ary2) { VALUE hash, ary3, v; st_table *table; st_data_t vv; long i; ary2 = to_ary(ary2 ary3 = rb_ary_new( if (RARRAY_LEN(ary2) == 0) return ary3; hash = ary_make_hash(ary2 table = rb_hash_tbl_raw(hash for (i=0; i<RARRAY_LEN(ary1 i++) { v = RARRAY_AREF(ary1, i vv = (st_data_t)v; if (st_delete(table, &vv, 0)) { rb_ary_push(ary3, v } } ary_recycle_hash(hash return ary3; }

ary * int → new_ary Show source

ary * str → new_string

Repetition - 使用String参数,等同于ary.join(str)

否则,返回通过连接int副本构建的新数组self

[ 1, 2, 3 ] * 3 #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ] [ 1, 2, 3 ] * "," #=> "1,2,3"

static VALUE rb_ary_times(VALUE ary, VALUE times) { VALUE ary2, tmp; const VALUE *ptr; long t, len; tmp = rb_check_string_type(times if (!NIL_P(tmp)) { return rb_ary_join(ary, tmp } len = NUM2LONG(times if (len == 0) { ary2 = ary_new(rb_obj_class(ary), 0 goto out; } if (len < 0) { rb_raise(rb_eArgError, "negative argument" } if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) { rb_raise(rb_eArgError, "argument too big" } len *= RARRAY_LEN(ary ary2 = ary_new(rb_obj_class(ary), len ARY_SET_LEN(ary2, len ptr = RARRAY_CONST_PTR(ary t = RARRAY_LEN(ary if (0 < t) { ary_memcpy(ary2, 0, t, ptr while (t <= len/2) { ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2) t *= 2; } if (t < len) { ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2) } } out: OBJ_INFECT(ary2, ary return ary2; }

ary + other_ary → new_ary Show source

串联 - 返回通过将两个数组连接在一起构建的新数组,以生成第三个数组。

[ 1, 2, 3 ] + [ 4, 5 ] #=> [ 1, 2, 3, 4, 5 ] a = [ "a", "b", "c" ] c = a + [ "d", "e", "f" ] c #=> [ "a", "b", "c", "d", "e", "f" ] a #=> [ "a", "b", "c" ]

注意

x += y

等同于

x = x + y

这意味着它会产生一个新的数组。结果,重复使用+=阵列可能效率很低。

另见#concat。

VALUE rb_ary_plus(VALUE x, VALUE y) { VALUE z; long len, xlen, ylen; y = to_ary(y xlen = RARRAY_LEN(x ylen = RARRAY_LEN(y len = xlen + ylen; z = rb_ary_new2(len ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x) ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y) ARY_SET_LEN(z, len return z; }

ary - other_ary → new_ary Show source

阵列差异

返回作为原始数组副本的新数组,删除所有也出现在其中的项目other_ary。订单从原始数组中保留。

它使用hash和eql比较元素?提高效率的方法。

[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ] #=> [ 3, 3, 5 ]

如果您需要类似设置的行为,请参阅库类Set。

static VALUE rb_ary_diff(VALUE ary1, VALUE ary2) { VALUE ary3; VALUE hash; long i; hash = ary_make_hash(to_ary(ary2) ary3 = rb_ary_new( for (i=0; i<RARRAY_LEN(ary1 i++) { if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue; rb_ary_push(ary3, rb_ary_elt(ary1, i) } ary_recycle_hash(hash return ary3; }

ary << obj → ary Show source

追加 - 将给定的对象推到该数组的末尾。该表达式返回数组本身,因此可以将几个附加链接在一起。

[ 1, 2 ] << "c" << "d" << [ 3, 4 ] #=> [ 1, 2, "c", "d", [ 3, 4 ] ]

VALUE rb_ary_push(VALUE ary, VALUE item) { long idx = RARRAY_LEN(ary VALUE target_ary = ary_ensure_room_for_push(ary, 1 RARRAY_PTR_USE(ary, ptr, { RB_OBJ_WRITE(target_ary, &ptr[idx], item } ARY_SET_LEN(ary, idx + 1 return ary; }

ary <=> other_ary → -1, 0, +1 or nil Show source

比较 - 如果此数组小于,等于或大于other_ary,则返回整数(-1,0或+1)。

比较每个数组中的每个对象(使用<=>运算符)。

数组以“元素明智”的方式进行比较; 第一个元素ary与第一个other_ary使用<=>运算符,然后每个第二个元素等进行比较。只要任何这样的比较结果非零(即两个对应的元素不相等),该结果将返回整个数组比较。

如果所有元素都相等,则结果将基于数组长度的比较。因此,根据Array#<=>,两个数组“相等”,当且仅当它们具有相同的长度并且每个元素的值等于另一个数组中相应元素的值时。

如果other_ary不是数组或者返回两个元素的比较,则返回nil

[ "a", "a", "c" ] <=> [ "a", "b", "c" ] #=> -1 [ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ] #=> +1 [ 1, 2 ] <=> [ 1, :two ] #=> nil

VALUE rb_ary_cmp(VALUE ary1, VALUE ary2) { long len; VALUE v; ary2 = rb_check_array_type(ary2 if (NIL_P(ary2)) return Qnil; if (ary1 == ary2) return INT2FIX(0 v = rb_exec_recursive_paired(recursive_cmp, ary1, ary2, ary2 if (v != Qundef) return v; len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2 if (len == 0) return INT2FIX(0 if (len > 0) return INT2FIX(1 return INT2FIX(-1 }

ary == other_ary → bool Show source

相等 - 如果两个数组包含相同数量的元素并且每个元素等于(根据Object#==)other_ary中的相应元素,则两个数组相等。

[ "a", "c" ] == [ "a", "c", 7 ] #=> false [ "a", "c", 7 ] == [ "a", "c", 7 ] #=> true [ "a", "c", 7 ] == [ "a", "d", "f" ] #=> false

static VALUE rb_ary_equal(VALUE ary1, VALUE ary2) { if (ary1 == ary2) return Qtrue; if (!RB_TYPE_P(ary2, T_ARRAY)) { if (!rb_respond_to(ary2, idTo_ary)) { return Qfalse; } return rb_equal(ary2, ary1 } if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse; if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue; return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2 }

aryindex → obj or nil Show source

arystart, length → new_ary 或 nil

aryrange → new_ary 或 nil

slice(index) → obj 或 nil

slice(start, length) → new_ary 或 nil

slice(range) → new_ary 或 nil

元素参考 - 返回索引处的元素,或返回从开始索引处开始并继续长度元素的子阵列,或者返回由索引范围指定的子阵列。

负数索引从数组末尾向后计数(-1是最后一个元素)。 对于开始和范围情况,起始索引就在元素之前。 此外,当元素范围的起始索引位于数组的末尾时,将返回一个空数组。

如果索引(或起始索引)超出范围则返回nil

a = [ "a", "b", "c", "d", "e" ] a[2] + a[0] + a[1] #=> "cab" a[6] #=> nil a[1, 2] #=> [ "b", "c" ] a[1..3] #=> [ "b", "c", "d" ] a[4..7] #=> [ "e" ] a[6..10] #=> nil a[-3, 3] #=> [ "c", "d", "e" ] # special cases a[5] #=> nil a[6, 1] #=> nil a[5, 1] #=> [] a[5..10] #=> []

VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary) { VALUE arg; long beg, len; if (argc == 2) { beg = NUM2LONG(argv[0] len = NUM2LONG(argv[1] if (beg < 0) { beg += RARRAY_LEN(ary } return rb_ary_subseq(ary, beg, len } if (argc != 1) { rb_scan_args(argc, argv, "11", NULL, NULL } arg = argv[0]; /* special case - speeding up */ if (FIXNUM_P(arg)) { return rb_ary_entry(ary, FIX2LONG(arg) } /* check if idx is Range */ switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) { case Qfalse: break; case Qnil: return Qnil; default: return rb_ary_subseq(ary, beg, len } return rb_ary_entry(ary, NUM2LONG(arg) }

aryindex = obj → obj Show source

arystart,length = obj或other_ary或nil→obj或other_ary或nil

aryrange = obj or other_ary or nil → obj or other_ary or nil

元素分配 - 在索引处设置元素,或者从长度元素的开始索引处替换子数组,或者替换由索引范围指定的子数组。

如果索引大于数组的当前容量,则数组会自动增长。 如果长度为零,元素将在开始时插入到数组中。

负指数将从数组末尾向后计数。 对于开始和范围情况,起始索引就在元素之前。

如果负指数指向数组的开始位置,则会引发IndexError。

另请参阅#push和#unshift。

a = Array.new a[4] = "4"; #=> [nil, nil, nil, nil, "4"] a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"] a[1..2] = [ 1, 2 ] #=> ["a", 1, 2, nil, "4"] a[0, 2] = "?" #=> ["?", 2, nil, "4"] a[0..2] = "A" #=> ["A", "4"] a[-1] = "Z" #=> ["A", "Z"] a[1..-1] = nil #=> ["A", nil] a[1..-1] = [] #=> ["A"] a[0, 0] = [ 1, 2 ] #=> [1, 2, "A"] a[3, 0] = "B" #=> [1, 2, "A", "B"]

static VALUE rb_ary_aset(int argc, VALUE *argv, VALUE ary) { long offset, beg, len; VALUE rpl; if (argc == 3) { rb_ary_modify_check(ary beg = NUM2LONG(argv[0] len = NUM2LONG(argv[1] goto range; } rb_check_arity(argc, 2, 2 rb_ary_modify_check(ary if (FIXNUM_P(argv[0])) { offset = FIX2LONG(argv[0] goto fixnum; } if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) { /* check if idx is Range */ range: rpl = rb_ary_to_ary(argv[argc-1] rb_ary_splice(ary, beg, len, RARRAY_CONST_PTR(rpl), RARRAY_LEN(rpl) RB_GC_GUARD(rpl return argv[argc-1]; } offset = NUM2LONG(argv[0] fixnum: rb_ary_store(ary, offset, argv[1] return argv[1]; }

abbrev(pattern = nil) Show source

计算字符串中明确缩写的集合self

require 'abbrev' %w{ car cone }.abbrev #=> {"car"=>"car", "ca"=>"car", "cone"=>"cone", "con"=>"cone", "co"=>"cone"}

可选pattern参数是一个模式或一个字符串。输出哈希中只包含匹配模式或以字符串开头的输入字符串。

%w{ fast boat day }.abbrev(/^.a/) #=> {"fast"=>"fast", "fas"=>"fast", "fa"=>"fast", "day"=>"day", "da"=>"day"} Abbrev.abbrev(%w{car box cone}, "ca") #=> {"car"=>"car", "ca"=>"car"}

另见Abbrev#abbrev

# File lib/abbrev.rb, line 128 def abbrev(pattern = nil) Abbrev::abbrev(self, pattern) end

any? { |obj| block } → true or false Show source

另请参阅Enumerable#any?

static VALUE rb_ary_any_p(VALUE ary) { long i, len = RARRAY_LEN(ary const VALUE *ptr = RARRAY_CONST_PTR(ary if (!len) return Qfalse; if (!rb_block_given_p()) { for (i = 0; i < len; ++i) if (RTEST(ptr[i])) return Qtrue; } else { for (i = 0; i < RARRAY_LEN(ary ++i) { if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue; } } return Qfalse; }

assoc(obj) → element_ary or nil Show source

搜索一个数组,其元素也是数组,比较obj每个包含数组的第一个元素obj.==

返回匹配的第一个包含数组(即,第一个关联数组),或者如果找不到匹配项则返回nil

另见#rassoc

s1 = [ "colors", "red", "blue", "green" ] s2 = [ "letters", "a", "b", "c" ] s3 = "foo" a = [ s1, s2, s3 ] a.assoc("letters") #=> [ "letters", "a", "b", "c" ] a.assoc("foo") #=> nil

VALUE rb_ary_assoc(VALUE ary, VALUE key) { long i; VALUE v; for (i = 0; i < RARRAY_LEN(ary ++i) { v = rb_check_array_type(RARRAY_AREF(ary, i) if (!NIL_P(v) && RARRAY_LEN(v) > 0 && rb_equal(RARRAY_AREF(v, 0), key)) return v; } return Qnil; }

at(index) → obj or nil Show source

返回索引处的元素。 负面指数从自我结束时开始计算。 如果索引超出范围,则返回nil。 也可以看看 #[]。

a = [ "a", "b", "c", "d", "e" ] a.at(0) #=> "a" a.at(-1) #=> "e"

VALUE rb_ary_at(VALUE ary, VALUE pos) { return rb_ary_entry(ary, NUM2LONG(pos) }

bsearch {|x| block } → elem Show source

通过使用二分搜索,从这个数组中找到一个符合O(log n)中给定条件的值,其中n是数组的大小。

您可以在两种使用情况下使用此方法:查找最小模式和查找任何模式。在任何一种情况下,数组的元素必须相对于该块单调(或排序)。

在find-minimum模式下(对于典型用例来说这是一个很好的选择),块必须返回true或false,并且必须有索引i(0 <= i <= ary.size),以便:

  • 对于索引小于i的任何元素,块返回false

  • 对于索引大于或等于i的任何元素,块返回true。

这个方法返回第i个元素。如果我等于ary.size,则返回nil。

ary = [0, 4, 7, 10, 12] ary.bsearch {|x| x >= 4 } #=> 4 ary.bsearch {|x| x >= 6 } #=> 7 ary.bsearch {|x| x >= -1 } #=> 0 ary.bsearch {|x| x >= 100 } #=> nil

在find-any模式下(这与libc的bsearch(3)相似),块必须返回一个数字,并且必须有两个索引i和j(0 <= i <= j <= ary.size),以便:

  • 如果0 <= k <i,块返回一个正数,

  • 如果i <= k <j,则该块返回为零,并且

  • 如果j <= k <ary.size,块返回ary的负数。

在这种情况下,此方法返回索引在i ... j之内的任何元素。如果我等于j(即,没有满足块的元素),则此方法返回nil。

ary = [0, 4, 7, 10, 12] # try to find v such that 4 <= v < 8 ary.bsearch {|x| 1 - x / 4 } #=> 4 or 7 # try to find v such that 8 <= v < 10 ary.bsearch {|x| 4 - x / 2 } #=> nil

你不能一次混合两种模式; 该块必须始终返回true / false,或始终返回一个数字。它没有定义在每次迭代中实际选取哪个值。

static VALUE rb_ary_bsearch(VALUE ary) { VALUE index_result = rb_ary_bsearch_index(ary if (FIXNUM_P(index_result)) { return rb_ary_entry(ary, FIX2LONG(index_result) } return index_result; }

bsearch_index {|x| block } → int or nil Show source

通过使用二进制搜索,从这个数组中找到符合给定条件的值的索引,其中n是数组的大小。

它支持两种模式,具体取决于块的性质,它们与bsearch方法完全相同,唯一的区别是此方法返回元素的索引而不是元素本身。有关更多详细信息,请参阅bsearch的文档。

static VALUE rb_ary_bsearch_index(VALUE ary) { long low = 0, high = RARRAY_LEN(ary), mid; int smaller = 0, satisfied = 0; VALUE v, val; RETURN_ENUMERATOR(ary, 0, 0 while (low < high) { mid = low + ((high - low) / 2 val = rb_ary_entry(ary, mid v = rb_yield(val if (FIXNUM_P(v)) { if (v == INT2FIX(0)) return INT2FIX(mid smaller = (SIGNED_VALUE)v < 0; /* Fixnum preserves its sign-bit */ } else if (v == Qtrue) { satisfied = 1; smaller = 1; } else if (v == Qfalse || v == Qnil) { smaller = 0; } else if (rb_obj_is_kind_of(v, rb_cNumeric)) { const VALUE zero = INT2FIX(0 switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, zero)) { case 0: return INT2FIX(mid case 1: smaller = 1; break; case -1: smaller = 0; } } else { rb_raise(rb_eTypeError, "wrong argument type %"PRIsVALUE " (must be numeric, true, false or nil)", rb_obj_class(v) } if (smaller) { high = mid; } else { low = mid + 1; } } if (!satisfied) return Qnil; return INT2FIX(low }

clear → ary Show source

self中删除所有元素。

a = [ "a", "b", "c", "d", "e" ] a.clear #=> [ ]

VALUE rb_ary_clear(VALUE ary) { rb_ary_modify_check(ary ARY_SET_LEN(ary, 0 if (ARY_SHARED_P(ary)) { if (!ARY_EMBED_P(ary)) { rb_ary_unshare(ary FL_SET_EMBED(ary } } else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) { ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2 } return ary; }

collect { |item| block } → new_ary Show source

collect → Enumerator

为每个自我元素调用一次给定的块。

创建一个包含块返回值的新数组。

另请参阅Enumerable#collect。

如果没有给出块,则返回一个枚举器。

a = [ "a", "b", "c", "d" ] a.collect { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"] a.map.with_index { |x, i| x * i } #=> ["", "b", "cc", "ddd"] a #=> ["a", "b", "c", "d"]

static VALUE rb_ary_collect(VALUE ary) { long i; VALUE collect; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length collect = rb_ary_new2(RARRAY_LEN(ary) for (i = 0; i < RARRAY_LEN(ary i++) { rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)) } return collect; }

collect! {|item| block } → ary Show source

collect! → Enumerator

为自己的每个元素调用给定的块一次,用该块返回的值替换元素。

另请参阅Enumerable#collect。

如果没有给出块,则返回一个枚举器。

a = [ "a", "b", "c", "d" ] a.map! {|x| x + "!" } a #=> [ "a!", "b!", "c!", "d!" ] a.collect!.with_index {|x, i| x[0...i] } a #=> ["", "b", "c!", "d!"]

static VALUE rb_ary_collect_bang(VALUE ary) { long i; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length rb_ary_modify(ary for (i = 0; i < RARRAY_LEN(ary i++) { rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)) } return ary; }

combination(n) { |c| block } → ary Show source

combination(n) → Enumerator

当用块调用时,产生数组中元素长度为n的所有组合,然后返回数组本身。

该实施不保证组合产生的顺序。

如果没有给出块,则返回一个枚举器。

例子:

a = [1, 2, 3, 4] a.combination(1).to_a #=> [[1],[2],[3],[4]] a.combination(2).to_a #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]] a.combination(3).to_a #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]] a.combination(4).to_a #=> [[1,2,3,4]] a.combination(0).to_a #=> [[]] # one combination of length 0 a.combination(5).to_a #=> [] # no combinations of length 5

static VALUE rb_ary_combination(VALUE ary, VALUE num) { long i, n, len; n = NUM2LONG(num RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_combination_size len = RARRAY_LEN(ary if (n < 0 || len < n) { /* yield nothing */ } else if (n == 0) { rb_yield(rb_ary_new2(0) } else if (n == 1) { for (i = 0; i < RARRAY_LEN(ary i++) { rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)) } } else { VALUE ary0 = ary_make_shared_copy(ary /* private defensive copy of ary */ volatile VALUE t0; long *stack = ALLOCV_N(long, t0, n+1 RBASIC_CLEAR_CLASS(ary0 combinate0(len, n, stack, ary0 ALLOCV_END(t0 RBASIC_SET_CLASS_RAW(ary0, rb_cArray } return ary; }

compact → new_ary Show source

返回删除了所有nil元素的self的副本。

[ "a", nil, "b", nil, "c", nil ].compact #=> [ "a", "b", "c" ]

static VALUE rb_ary_compact(VALUE ary) { ary = rb_ary_dup(ary rb_ary_compact_bang(ary return ary; }

compact! → ary or nil Show source

从数组中删除nil元素。

如果没有更改,则返回nil,否则返回数组。

[ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ] [ "a", "b", "c" ].compact! #=> nil

static VALUE rb_ary_compact_bang(VALUE ary) { VALUE *p, *t, *end; long n; rb_ary_modify(ary p = t = (VALUE *)RARRAY_CONST_PTR(ary /* WB: no new reference */ end = p + RARRAY_LEN(ary while (t < end) { if (NIL_P(*t)) t++; else *p++ = *t++; } n = p - RARRAY_CONST_PTR(ary if (RARRAY_LEN(ary) == n) { return Qnil; } ary_resize_smaller(ary, n return ary; }

concat(other_ary1, other_ary2,...) → ary Show source

追加+ other_ary + s的元素到self

[ "a", "b" ].concat( ["c", "d"] ) #=> [ "a", "b", "c", "d" ] [ "a" ].concat( ["b"], ["c", "d"] ) #=> [ "a", "b", "c", "d" ] [ "a" ].concat #=> [ "a" ] a = [ 1, 2, 3 ] a.concat( [ 4, 5 ] ) a #=> [ 1, 2, 3, 4, 5 ] a = [ 1, 2 ] a.concat(a, a) #=> [1, 2, 1, 2, 1, 2]

另请参阅Array#+。

static VALUE rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary) { rb_ary_modify_check(ary if (argc > 0) { int i; VALUE args = rb_ary_tmp_new(argc for (i = 0; i < argc; i++) { rb_ary_concat(args, argv[i] } ary_append(ary, args } return ary; }

count → int Show source

count(obj) → int

count { |item| block } → int

返回元素的数量。

如果给出参数,则使用==来计算等于obj的元素的数量。

如果给出了一个块,则计算该块返回一个真值的元素的数量。

ary = [1, 2, 4, 2] ary.count #=> 4 ary.count(2) #=> 2 ary.count { |x| x%2 == 0 } #=> 3

static VALUE rb_ary_count(int argc, VALUE *argv, VALUE ary) { long i, n = 0; if (argc == 0) { VALUE v; if (!rb_block_given_p()) return LONG2NUM(RARRAY_LEN(ary) for (i = 0; i < RARRAY_LEN(ary i++) { v = RARRAY_AREF(ary, i if (RTEST(rb_yield(v))) n++; } } else { VALUE obj; rb_scan_args(argc, argv, "1", &obj if (rb_block_given_p()) { rb_warn("given block not used" } for (i = 0; i < RARRAY_LEN(ary i++) { if (rb_equal(RARRAY_AREF(ary, i), obj)) n++; } } return LONG2NUM(n }

cycle(n=nil) { |obj| block } → nil Show source

cycle(n=nil) → Enumerator

如果给出零,则为每个元素调用给定块n次或永远。

如果给出了一个非正数或者数组是空的,则不做任何事情。

如果循环完成而没有被中断,则返回nil。

如果没有给出块,则返回一个枚举器。

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

static VALUE rb_ary_cycle(int argc, VALUE *argv, VALUE ary) { long n, i; VALUE nv = Qnil; rb_scan_args(argc, argv, "01", &nv RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size if (NIL_P(nv)) { n = -1; } else { n = NUM2LONG(nv if (n <= 0) return Qnil; } while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) { for (i=0; i<RARRAY_LEN(ary i++) { rb_yield(RARRAY_AREF(ary, i) } } return Qnil; }

dclone() Show source

提供统一的克隆操作,以便REXML :: XPathParser跨多个Object +类型使用

# File lib/rexml/xpath_parser.rb, line 32 def dclone klone = self.clone klone.clear self.each{|v| klone << v.dclone} klone end

delete(obj) → item or nil Show source

delete(obj) { block } → item or result of block

从self删除所有等于obj的项目。

返回上次删除的项目,如果找不到匹配的项目,则返回nil。

如果给出了可选的代码块,如果找不到该项目,则返回该块的结果。(要删除nil元素并获得丰富的返回值,请使用#compact!)

a = [ "a", "b", "b", "b", "c" ] a.delete("b") #=> "b" a #=> ["a", "c"] a.delete("z") #=> nil a.delete("z") { "not found" } #=> "not found"

VALUE rb_ary_delete(VALUE ary, VALUE item) { VALUE v = item; long i1, i2; for (i1 = i2 = 0; i1 < RARRAY_LEN(ary i1++) { VALUE e = RARRAY_AREF(ary, i1 if (rb_equal(e, item)) { v = e; continue; } if (i1 != i2) { rb_ary_store(ary, i2, e } i2++; } if (RARRAY_LEN(ary) == i2) { if (rb_block_given_p()) { return rb_yield(item } return Qnil; } ary_resize_smaller(ary, i2 return v; }

delete_at(index) → obj or nil Show source

删除指定索引处的元素,返回该元素;如果索引超出范围,则删除该元素。

另见#slice!

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

static VALUE rb_ary_delete_at_m(VALUE ary, VALUE pos) { return rb_ary_delete_at(ary, NUM2LONG(pos) }

delete_if { |item| block } → ary Show source

delete_if → Enumerator

删除块评估为真的每个自我元素。

每次调用块时,数组都会立即更改,而不是在迭代结束后更改。

另见#reject!

如果没有给出块,则返回一个枚举器。

scores = [ 97, 42, 75 ] scores.delete_if {|score| score < 80 } #=> [97]

static VALUE rb_ary_delete_if(VALUE ary) { RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length ary_reject_bang(ary return ary; }

dig(idx, ...) → object Show source

通过在每个步骤调用dig提取由idx对象序列指定的嵌套值,如果任何中间步骤为零,则返回nil。

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

VALUE rb_ary_dig(int argc, VALUE *argv, VALUE self) { rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS self = rb_ary_at(self, *argv if (!--argc) return self; ++argv; return rb_obj_dig(argc, argv, self, Qnil }

drop(n) → new_ary Show source

从ary中删除前n个元素,并将其余元素返回到数组中。

如果给出一个负数,则引发一个ArgumentError。

另见#take

a = [1, 2, 3, 4, 5, 0] a.drop(3) #=> [4, 5, 0]

static VALUE rb_ary_drop(VALUE ary, VALUE n) { VALUE result; long pos = NUM2LONG(n if (pos < 0) { rb_raise(rb_eArgError, "attempt to drop negative size" } result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary) if (result == Qnil) result = rb_ary_new( return result; }

drop_while { |obj| block } → new_ary Show source

drop_while → Enumerator

将元素删除,但不包括块返回nil或false的第一个元素,并返回包含其余元素的数组。

如果没有给出块,则返回一个枚举器。

另见#take_while

a = [1, 2, 3, 4, 5, 0] a.drop_while {|i| i < 3 } #=> [3, 4, 5, 0]

static VALUE rb_ary_drop_while(VALUE ary) { long i; RETURN_ENUMERATOR(ary, 0, 0 for (i = 0; i < RARRAY_LEN(ary i++) { if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break; } return rb_ary_drop(ary, LONG2FIX(i) }

each { |item| block } → ary Show source

each → Enumerator

为每个元素调用一次给定的块self,将该元素作为参数传递。返回数组本身。

如果没有给出块,则返回枚举器。

a = [ "a", "b", "c" ] a.each {|x| print x, " -- " }

产生结果:

a -- b -- c --

VALUE rb_ary_each(VALUE ary) { long i; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length for (i=0; i<RARRAY_LEN(ary i++) { rb_yield(RARRAY_AREF(ary, i) } return ary; }

each_index { |index| block } → ary Show source

each_index → Enumerator

与#each相同,但传递元素的索引而不是元素本身。

如果没有给出块,则枚举器返回。

a = [ "a", "b", "c" ] a.each_index {|x| print x, " -- " }

产生结果:

0 -- 1 -- 2 --

static VALUE rb_ary_each_index(VALUE ary) { long i; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length for (i=0; i<RARRAY_LEN(ary i++) { rb_yield(LONG2NUM(i) } return ary; }

empty? → true or false Show source

如果self不包含元素,则返回true。

[].empty? #=> true

static VALUE rb_ary_empty_p(VALUE ary) { if (RARRAY_LEN(ary) == 0) return Qtrue; return Qfalse; }

eql?(other) → true or false Show source

如果self和other是同一个对象,或者都是相同内容的数组(根据Object#eql?),则返回true。

static VALUE rb_ary_eql(VALUE ary1, VALUE ary2) { if (ary1 == ary2) return Qtrue; if (!RB_TYPE_P(ary2, T_ARRAY)) return Qfalse; if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse; if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue; return rb_exec_recursive_paired(recursive_eql, ary1, ary2, ary2 }

fetch(index) → obj Show source

fetch(index, default) → obj

fetch(index) { |index| block } → obj

尝试返回位置index处的元素,但如果引用的索引位于数组边界之外,则会引发IndexError异常。 通过提供第二个参数可以防止此错误,该参数将用作默认值。

另外,如果给出了一个块,它只会在引用无效索引时执行。

index数组尾数的负值。

a = [ 11, 22, 33, 44 ] a.fetch(1) #=> 22 a.fetch(-1) #=> 44 a.fetch(4, 'cat') #=> "cat" a.fetch(100) { |i| puts "#{i} is out of bounds" } #=> "100 is out of bounds"

static VALUE rb_ary_fetch(int argc, VALUE *argv, VALUE ary) { VALUE pos, ifnone; long block_given; long idx; rb_scan_args(argc, argv, "11", &pos, &ifnone block_given = rb_block_given_p( if (block_given && argc == 2) { rb_warn("block supersedes default value argument" } idx = NUM2LONG(pos if (idx < 0) { idx += RARRAY_LEN(ary } if (idx < 0 || RARRAY_LEN(ary) <= idx) { if (block_given) return rb_yield(pos if (argc == 1) { rb_raise(rb_eIndexError, "index %ld outside of array bounds: %ld...%ld", idx - (idx < 0 ? RARRAY_LEN(ary) : 0), -RARRAY_LEN(ary), RARRAY_LEN(ary) } return ifnone; } return RARRAY_AREF(ary, idx }

fill(obj) → ary Show source

fill(obj, start , length) → ary

fill(obj, range ) → ary

fill { |index| block } → ary

fill(start , length ) { |index| block } → ary

fill(range) { |index| block } → ary

前三种形式将self(可能是整个数组)的选定元素设置为obj。

nil的start等于零。

nil的length等效于所述阵列的长度。

最后三种形式使用给定块的值填充数组,该块将传递每个要填充的元素的绝对索引。

从数组末尾开始计数的负值,其中-1是最后一个元素。

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

static VALUE rb_ary_fill(int argc, VALUE *argv, VALUE ary) { VALUE item = Qundef, arg1, arg2; long beg = 0, end = 0, len = 0; if (rb_block_given_p()) { rb_scan_args(argc, argv, "02", &arg1, &arg2 argc += 1; /* hackish */ } else { rb_scan_args(argc, argv, "12", &item, &arg1, &arg2 } switch (argc) { case 1: beg = 0; len = RARRAY_LEN(ary break; case 2: if (rb_range_beg_len(arg1, &beg, &len, RARRAY_LEN(ary), 1)) { break; } /* fall through */ case 3: beg = NIL_P(arg1) ? 0 : NUM2LONG(arg1 if (beg < 0) { beg = RARRAY_LEN(ary) + beg; if (beg < 0) beg = 0; } len = NIL_P(arg2) ? RARRAY_LEN(ary) - beg : NUM2LONG(arg2 break; } rb_ary_modify(ary if (len < 0) { return ary; } if (beg >= ARY_MAX_SIZE || len > ARY_MAX_SIZE - beg) { rb_raise(rb_eArgError, "argument too big" } end = beg + len; if (RARRAY_LEN(ary) < end) { if (end >= ARY_CAPA(ary)) { ary_resize_capa(ary, end } ary_mem_clear(ary, RARRAY_LEN(ary), end - RARRAY_LEN(ary) ARY_SET_LEN(ary, end } if (item == Qundef) { VALUE v; long i; for (i=beg; i<end; i++) { v = rb_yield(LONG2NUM(i) if (i>=RARRAY_LEN(ary)) break; ARY_SET(ary, i, v } } else { ary_memfill(ary, beg, len, item } return ary; }

find_index(obj) → int or nil Show source

find_index { |item| block } → int or nil

find_index → Enumerator

返回ary中第一个对象的索引,使对象为== to obj。

如果给出的是块而不是参数,则返回块返回true的第一个对象的索引。 如果找不到匹配,则返回nil。

另见#rindex。

如果没有给出块或参数,则返回枚举器。

a = [ "a", "b", "c" ] a.index("b") #=> 1 a.index("z") #=> nil a.index { |x| x == "b" } #=> 1

static VALUE rb_ary_index(int argc, VALUE *argv, VALUE ary) { const VALUE *ptr; VALUE val; long i, len; if (argc == 0) { RETURN_ENUMERATOR(ary, 0, 0 for (i=0; i<RARRAY_LEN(ary i++) { if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) { return LONG2NUM(i } } return Qnil; } rb_check_arity(argc, 0, 1 val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used" len = RARRAY_LEN(ary ptr = RARRAY_CONST_PTR(ary for (i=0; i<len; i++) { VALUE e = ptr[i]; switch (rb_equal_opt(e, val)) { case Qundef: if (!rb_equal(e, val)) break; case Qtrue: return LONG2NUM(i case Qfalse: continue; } len = RARRAY_LEN(ary ptr = RARRAY_CONST_PTR(ary } return Qnil; }

first → obj or nil Show source

first(n) → new_ary

返回n数组的第一个元素或第一个元素。如果数组为空,则返回第一个表单nil,而第二个表单返回一个空数组。另请参阅#last以获得相反的效果。

a = [ "q", "r", "s", "t" ] a.first #=> "q" a.first(2) #=> ["q", "r"]

static VALUE rb_ary_first(int argc, VALUE *argv, VALUE ary) { if (argc == 0) { if (RARRAY_LEN(ary) == 0) return Qnil; return RARRAY_AREF(ary, 0 } else { return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST } }

flatten → new_ary Show source

flatten(level) → new_ary

返回一个新的数组,它是self递归的一维平坦化。

也就是说,对于数组中的每个元素,将其元素提取到新数组中。

可选level参数确定递归的级别。

s = [ 1, 2, 3 ] #=> [1, 2, 3] t = [ 4, 5, 6, [7, 8] ] #=> [4, 5, 6, [7, 8]] a = [ s, t, 9, 10 ] #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10] a.flatten #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] a = [ 1, 2, [3, [4, 5] ] ] a.flatten(1) #=> [1, 2, 3, [4, 5]]

static VALUE rb_ary_flatten(int argc, VALUE *argv, VALUE ary) { int mod = 0, level = -1; VALUE result, lv; rb_scan_args(argc, argv, "01", &lv if (!NIL_P(lv)) level = NUM2INT(lv if (level == 0) return ary_make_shared_copy(ary result = flatten(ary, level, &mod OBJ_INFECT(result, ary return result; }

flatten! → ary or nil Show source

flatten!(level) → ary or nil

Flattens self in place.

如果未做任何修改,则返回nil(即数组不包含子数组)。

可选level参数确定递归的级别。

a = [ 1, 2, [3, [4, 5] ] ] a.flatten! #=> [1, 2, 3, 4, 5] a.flatten! #=> nil a #=> [1, 2, 3, 4, 5] a = [ 1, 2, [3, [4, 5] ] ] a.flatten!(1) #=> [1, 2, 3, [4, 5]]

static VALUE rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary) { int mod = 0, level = -1; VALUE result, lv; rb_scan_args(argc, argv, "01", &lv rb_ary_modify_check(ary if (!NIL_P(lv)) level = NUM2INT(lv if (level == 0) return Qnil; result = flatten(ary, level, &mod if (mod == 0) { ary_discard(result return Qnil; } if (!(mod = ARY_EMBED_P(result))) rb_obj_freeze(result rb_ary_replace(ary, result if (mod) ARY_SET_EMBED_LEN(result, 0 return ary; }

frozen? → true or false Show source

如果此数组被冻结(或在排序时暂时冻结),则返回true。 另请参见对象#冻结?

static VALUE rb_ary_frozen_p(VALUE ary) { if (OBJ_FROZEN(ary)) return Qtrue; return Qfalse; }

hash → integer Show source

计算这个数组的散列码。

两个具有相同内容的数组将具有相同的哈希代码(并将使用eql进行比较?)。

另见对象#散列。

static VALUE rb_ary_hash(VALUE ary) { long i; st_index_t h; VALUE n; h = rb_hash_start(RARRAY_LEN(ary) h = rb_hash_uint(h, (st_index_t)rb_ary_hash for (i=0; i<RARRAY_LEN(ary i++) { n = rb_hash(RARRAY_AREF(ary, i) h = rb_hash_uint(h, NUM2LONG(n) } h = rb_hash_end(h return ST2FIX(h }

include?(object) → true or false Show source

如果给定对象存在于self中(即,如果有任何元素==对象),则返回true,否则返回false。

a = [ "a", "b", "c" ] a.include?("b") #=> true a.include?("z") #=> false

VALUE rb_ary_includes(VALUE ary, VALUE item) { long i; VALUE e; for (i=0; i<RARRAY_LEN(ary i++) { e = RARRAY_AREF(ary, i switch (rb_equal_opt(e, item)) { case Qundef: if (rb_equal(e, item)) return Qtrue; break; case Qtrue: return Qtrue; } } return Qfalse; }

index(obj) → int or nil Show source

index { |item| block } → int or nil

index → Enumerator

返回ary中第一个对象的索引,使对象为== to obj。

如果给出的是块而不是参数,则返回块返回true的第一个对象的索引。 如果找不到匹配,则返回nil。

另见#rindex。

如果没有给出块或参数,则返回枚举器。

a = [ "a", "b", "c" ] a.index("b") #=> 1 a.index("z") #=> nil a.index { |x| x == "b" } #=> 1

static VALUE rb_ary_index(int argc, VALUE *argv, VALUE ary) { const VALUE *ptr; VALUE val; long i, len; if (argc == 0) { RETURN_ENUMERATOR(ary, 0, 0 for (i=0; i<RARRAY_LEN(ary i++) { if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) { return LONG2NUM(i } } return Qnil; } rb_check_arity(argc, 0, 1 val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used" len = RARRAY_LEN(ary ptr = RARRAY_CONST_PTR(ary for (i=0; i<len; i++) { VALUE e = ptr[i]; switch (rb_equal_opt(e, val)) { case Qundef: if (!rb_equal(e, val)) break; case Qtrue: return LONG2NUM(i case Qfalse: continue; } len = RARRAY_LEN(ary ptr = RARRAY_CONST_PTR(ary } return Qnil; }

initialize_copy(other_ary) → ary Show source

用other_ary的内容替换self的内容,如有必要,截断或扩展。

a = [ "a", "b", "c", "d", "e" ] a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"] a #=> ["x", "y", "z"]

VALUE rb_ary_replace(VALUE copy, VALUE orig) { rb_ary_modify_check(copy orig = to_ary(orig if (copy == orig) return copy; if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) { VALUE shared = 0; if (ARY_OWNS_HEAP_P(copy)) { RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)) } else if (ARY_SHARED_P(copy)) { shared = ARY_SHARED(copy FL_UNSET_SHARED(copy } FL_SET_EMBED(copy ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig) if (shared) { rb_ary_decrement_share(shared } ARY_SET_LEN(copy, RARRAY_LEN(orig) } else { VALUE shared = ary_make_shared(orig if (ARY_OWNS_HEAP_P(copy)) { RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)) } else { rb_ary_unshare_safe(copy } FL_UNSET_EMBED(copy ARY_SET_PTR(copy, RARRAY_CONST_PTR(orig) ARY_SET_LEN(copy, RARRAY_LEN(orig) rb_ary_set_shared(copy, shared } return copy; }

insert(index, obj...) → ary Show source

在具有给定索引的元素之前插入给定值。

负数从数组末尾向后计数,其中-1是最后一个元素。 如果使用负索引,则给定值将插入到该元素之后,因此使用-1的索引将在数组末尾插入值。

a = %w{ a b c d } a.insert(2, 99) #=> ["a", "b", 99, "c", "d"] a.insert(-2, 1, 2, 3) #=> ["a", "b", 99, "c", 1, 2, 3, "d"]

static VALUE rb_ary_insert(int argc, VALUE *argv, VALUE ary) { long pos; rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS rb_ary_modify_check(ary if (argc == 1) return ary; pos = NUM2LONG(argv[0] if (pos == -1) { pos = RARRAY_LEN(ary } if (pos < 0) { pos++; } rb_ary_splice(ary, pos, 0, argv + 1, argc - 1 return ary; }

inspect → string Show source

to_s → string

创建一个字符串表示self

[ "a", "b", "c" ].to_s #=> "[\"a\", \"b\", \"c\"]"

static VALUE rb_ary_inspect(VALUE ary) { if (RARRAY_LEN(ary) == 0) return rb_usascii_str_new2("[]" return rb_exec_recursive(inspect_ary, ary, 0 }

Also aliased as: to_s

join(separator=$,) → str Show source

返回一个通过将数组的每个元素转换为一个字符串而创建的字符串,由给定的分隔符分隔。 如果分隔符为零,则使用当前$ ,. 如果分隔符和$都是零,则它使用空字符串。

[ "a", "b", "c" ].join #=> "abc" [ "a", "b", "c" ].join("-") #=> "a-b-c"

static VALUE rb_ary_join_m(int argc, VALUE *argv, VALUE ary) { VALUE sep; rb_scan_args(argc, argv, "01", &sep if (NIL_P(sep)) sep = rb_output_fs; return rb_ary_join(ary, sep }

keep_if { |item| block } → ary Show source

keep_if → Enumerator

删除给定块评估为false的每个自身元素。

另请参阅#select!

如果没有给出块,则返回一个枚举器。

a = %w{ a b c d e f } a.keep_if { |v| v =~ /[aeiou]/ } #=> ["a", "e"]

static VALUE rb_ary_keep_if(VALUE ary) { RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length rb_ary_select_bang(ary return ary; }

last → obj or nil Show source

last(n) → new_ary

返回self的最后一个元素。 如果数组为空,则第一个窗体返回nil。

另请参阅#first,以获得相反的效果。

a = [ "w", "x", "y", "z" ] a.last #=> "z" a.last(2) #=> ["y", "z"]

VALUE rb_ary_last(int argc, const VALUE *argv, VALUE ary) { if (argc == 0) { long len = RARRAY_LEN(ary if (len == 0) return Qnil; return RARRAY_AREF(ary, len-1 } else { return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST } }

length → int Show source

返回self中的元素数量。 可能为零。

[ 1, 2, 3, 4, 5 ].length #=> 5 [].length #=> 0

static VALUE rb_ary_length(VALUE ary) { long len = RARRAY_LEN(ary return LONG2NUM(len }

还有别名:size

map { |item| block } → new_ary Show source

map → Enumerator

为每个元素调用一次给定的块self

创建一个包含块返回值的新数组。

另请参阅Enumerable#collect。

如果没有给出块,则返回一个枚举器。

a = [ "a", "b", "c", "d" ] a.collect { |x| x + "!" } #=> ["a!", "b!", "c!", "d!"] a.map.with_index { |x, i| x * i } #=> ["", "b", "cc", "ddd"] a #=> ["a", "b", "c", "d"]

static VALUE rb_ary_collect(VALUE ary) { long i; VALUE collect; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length collect = rb_ary_new2(RARRAY_LEN(ary) for (i = 0; i < RARRAY_LEN(ary i++) { rb_ary_push(collect, rb_yield(RARRAY_AREF(ary, i)) } return collect; }

map! {|item| block } → ary Show source

map! → Enumerator

为自己的每个元素调用给定的块一次,用该块返回的值替换元素。

另请参阅Enumerable#collect。

如果没有给出块,则返回一个枚举器。

a = [ "a", "b", "c", "d" ] a.map! {|x| x + "!" } a #=> [ "a!", "b!", "c!", "d!" ] a.collect!.with_index {|x, i| x[0...i] } a #=> ["", "b", "c!", "d!"]

static VALUE rb_ary_collect_bang(VALUE ary) { long i; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length rb_ary_modify(ary for (i = 0; i < RARRAY_LEN(ary i++) { rb_ary_store(ary, i, rb_yield(RARRAY_AREF(ary, i)) } return ary; }

max → obj Show source

max { |a, b| block } → obj

max(n) → array

max(n) { |a, b| block } → array

以最大值返回ary中的对象。第一种形式假定所有对象都实现Comparable; 第二个使用该块返回<=> b。

a = %w(albatross dog horse) a.max #=> "horse" a.max { |a, b| a.length <=> b.length } #=> "albatross"

如果n给出参数,则最大n元素将作为数组返回。

a = %w[albatross dog horse] a.max(2) #=> ["horse", "dog"] a.max(2) {|a, b| a.length <=> b.length } #=> ["albatross", "horse"]

static VALUE rb_ary_max(int argc, VALUE *argv, VALUE ary) { struct cmp_opt_data cmp_opt = { 0, 0 }; VALUE result = Qundef, v; VALUE num; long i; rb_scan_args(argc, argv, "01", &num if (!NIL_P(num)) return rb_nmin_run(ary, num, 0, 1, 1 if (rb_block_given_p()) { for (i = 0; i < RARRAY_LEN(ary i++) { v = RARRAY_AREF(ary, i if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) { result = v; } } } else { for (i = 0; i < RARRAY_LEN(ary i++) { v = RARRAY_AREF(ary, i if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) > 0) { result = v; } } } if (result == Qundef) return Qnil; return result; }

min → obj Show source

min {| a,b | block } → obj

min(n) → array

min(n) {| a,b | block } → array

以最小值返回ary中的对象。第一种形式假定所有对象都实现Comparable; 第二个使用该块返回<=> b。

a = %w(albatross dog horse) a.min #=> "albatross" a.min { |a, b| a.length <=> b.length } #=> "dog"

如果n给出参数,n则以数组形式返回最小元素。

a = %w[albatross dog horse] a.min(2) #=> ["albatross", "dog"] a.min(2) {|a, b| a.length <=> b.length } #=> ["dog", "horse"]

static VALUE rb_ary_min(int argc, VALUE *argv, VALUE ary) { struct cmp_opt_data cmp_opt = { 0, 0 }; VALUE result = Qundef, v; VALUE num; long i; rb_scan_args(argc, argv, "01", &num if (!NIL_P(num)) return rb_nmin_run(ary, num, 0, 0, 1 if (rb_block_given_p()) { for (i = 0; i < RARRAY_LEN(ary i++) { v = RARRAY_AREF(ary, i if (result == Qundef || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) { result = v; } } } else { for (i = 0; i < RARRAY_LEN(ary i++) { v = RARRAY_AREF(ary, i if (result == Qundef || OPTIMIZED_CMP(v, result, cmp_opt) < 0) { result = v; } } } if (result == Qundef) return Qnil; return result; }

pack( aTemplateString ) → aBinaryString Show source

pack( aTemplateString, buffer: aBufferString ) → aBufferString

根据aTemplateString中的指令将arr的内容打包成二进制序列(见下表)指令“A”,“a”,“Z”后面可以跟一个计数,该计数给出结果领域。其余指令也可能需要一个计数,指示要转换的数组元素的数量。如果计数是星号(“ *”),则所有其余的数组元素都将被转换。任何指令“ sSiIlL”“后面都可以加下划线(” _'“)或感叹号(” !“),以便将指定类型的底层平台的原始大小; 否则,他们使用平台无关的大小。空格在模板字符串中被忽略。另见String#unpack

a = [ "a", "b", "c" ] n = [ 65, 66, 67 ] a.pack("A3A3A3") #=> "a b c " a.pack("a3a3a3") #=> "a\000\000b\000\000c\000\000" n.pack("ccc") #=> "ABC"

如果指定了aBufferString并且其容量足够,pack则将其用作缓冲区并将其返回。当偏移由aTemplateString的开始指定时,结果将在偏移后填充。如果aBufferString的原始内容存在并且其长度大于偏移量,则offsetOfBuffer的其余部分将被结果覆盖。如果它更短,差距就会填充“ \0”。

请注意,“buffer:”选项不保证不分配内存。 如果aBufferString的容量不够,pack会分配内存。

指令pack

Integer | Array | Directive | Element | Meaning ---------------------------------------------------------------------------- C | Integer | 8-bit unsigned (unsigned char) S | Integer | 16-bit unsigned, native endian (uint16_t) L | Integer | 32-bit unsigned, native endian (uint32_t) Q | Integer | 64-bit unsigned, native endian (uint64_t) J | Integer | pointer width unsigned, native endian (uintptr_t) | | (J is available since Ruby 2.3.) | | c | Integer | 8-bit signed (signed char) s | Integer | 16-bit signed, native endian (int16_t) l | Integer | 32-bit signed, native endian (int32_t) q | Integer | 64-bit signed, native endian (int64_t) j | Integer | pointer width signed, native endian (intptr_t) | | (j is available since Ruby 2.3.) | | S_ S! | Integer | unsigned short, native endian I I_ I! | Integer | unsigned int, native endian L_ L! | Integer | unsigned long, native endian Q_ Q! | Integer | unsigned long long, native endian (ArgumentError | | if the platform has no long long type.) | | (Q_ and Q! is available since Ruby 2.1.) J! | Integer | uintptr_t, native endian (same with J) | | (J! is available since Ruby 2.3.) | | s_ s! | Integer | signed short, native endian i i_ i! | Integer | signed int, native endian l_ l! | Integer | signed long, native endian q_ q! | Integer | signed long long, native endian (ArgumentError | | if the platform has no long long type.) | | (q_ and q! is available since Ruby 2.1.) j! | Integer | intptr_t, native endian (same with j) | | (j! is available since Ruby 2.3.) | | S> s> S!> s!> | Integer | same as the directives without ">" except L> l> L!> l!> | | big endian I!> i!> | | (available since Ruby 1.9.3) Q> q> Q!> q!> | | "S>" is same as "n" J> j> J!> j!> | | "L>" is same as "N" | | S< s< S!< s!< | Integer | same as the directives without "<" except L< l< L!< l!< | | little endian I!< i!< | | (available since Ruby 1.9.3) Q< q< Q!< q!< | | "S<" is same as "v" J< j< J!< j!< | | "L<" is same as "V" | | n | Integer | 16-bit unsigned, network (big-endian) byte order N | Integer | 32-bit unsigned, network (big-endian) byte order v | Integer | 16-bit unsigned, VAX (little-endian) byte order V | Integer | 32-bit unsigned, VAX (little-endian) byte order | | U | Integer | UTF-8 character w | Integer | BER-compressed integer Float | Array | Directive | Element | Meaning --------------------------------------------------------------------------- D d | Float | double-precision, native format F f | Float | single-precision, native format E | Float | double-precision, little-endian byte order e | Float | single-precision, little-endian byte order G | Float | double-precision, network (big-endian) byte order g | Float | single-precision, network (big-endian) byte order String | Array | Directive | Element | Meaning --------------------------------------------------------------------------- A | String | arbitrary binary string (space padded, count is width) a | String | arbitrary binary string (null padded, count is width) Z | String | same as ``a'', except that null is added with * B | String | bit string (MSB first) b | String | bit string (LSB first) H | String | hex string (high nibble first) h | String | hex string (low nibble first) u | String | UU-encoded string M | String | quoted printable, MIME encoding (see RFC2045) m | String | base64 encoded string (see RFC 2045, count is width) | | (if count is 0, no line feed are added, see RFC 4648) P | String | pointer to a structure (fixed-length string) p | String | pointer to a null-terminated string Misc. | Array | Directive | Element | Meaning --------------------------------------------------------------------------- @ | --- | moves to absolute position X | --- | back up a byte x | --- | null byte

static VALUE pack_pack(int argc, VALUE *argv, VALUE ary) { static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0"; static const char spc10[] = " "; const char *p, *pend; VALUE fmt, opt = Qnil, res, from, associates = 0, buffer = 0; char type; long len, idx, plen; const char *ptr; int enc_info = 1; /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */ #ifdef NATINT_PACK int natint; /* native integer */ #endif int integer_size, bigendian_p; rb_scan_args(argc, argv, "10:", &fmt, &opt StringValue(fmt p = RSTRING_PTR(fmt pend = p + RSTRING_LEN(fmt if (!NIL_P(opt)) { static ID keyword_ids[1]; if (!keyword_ids[0]) CONST_ID(keyword_ids[0], "buffer" rb_get_kwargs(opt, keyword_ids, 0, 1, &buffer if (buffer != Qundef && !RB_TYPE_P(buffer, T_STRING)) rb_raise(rb_eTypeError, "buffer must be String, not %s", rb_obj_classname(buffer) } if (buffer) res = buffer; else res = rb_str_buf_new(0 idx = 0; #define TOO_FEW (rb_raise(rb_eArgError, toofew), 0) #define MORE_ITEM (idx < RARRAY_LEN(ary)) #define THISFROM (MORE_ITEM ? RARRAY_AREF(ary, idx) : TOO_FEW) #define NEXTFROM (MORE_ITEM ? RARRAY_AREF(ary, idx++) : TOO_FEW) while (p < pend) { int explicit_endian = 0; if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) { rb_raise(rb_eRuntimeError, "format string modified" } type = *p++; /* get data type */ #ifdef NATINT_PACK natint = 0; #endif if (ISSPACE(type)) continue; if (type == '#') { while ((p < pend) && (*p != '\n')) { p++; } continue; } { modifiers: switch (*p) { case '_': case '!': if (strchr(natstr, type)) { #ifdef NATINT_PACK natint = 1; #endif p++; } else { rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr } goto modifiers; case '<': case '>': if (!strchr(endstr, type)) { rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr } if (explicit_endian) { rb_raise(rb_eRangeError, "Can't use both '<' and '>'" } explicit_endian = *p++; goto modifiers; } } if (*p == '*') { /* set data length */ len = strchr("@Xxu", type) ? 0 : strchr("PMm", type) ? 1 : RARRAY_LEN(ary) - idx; p++; } else if (ISDIGIT(*p)) { errno = 0; len = STRTOUL(p, (char**)&p, 10 if (errno) { rb_raise(rb_eRangeError, "pack length too big" } } else { len = 1; } switch (type) { case 'U': /* if encoding is US-ASCII, upgrade to UTF-8 */ if (enc_info == 1) enc_info = 2; break; case 'm': case 'M': case 'u': /* keep US-ASCII (do nothing) */ break; default: /* fall back to BINARY */ enc_info = 0; break; } switch (type) { case 'A': case 'a': case 'Z': case 'B': case 'b': case 'H': case 'h': from = NEXTFROM; if (NIL_P(from)) { ptr = ""; plen = 0; } else { StringValue(from ptr = RSTRING_PTR(from plen = RSTRING_LEN(from OBJ_INFECT(res, from } if (p[-1] == '*') len = plen; switch (type) { case 'a': /* arbitrary binary string (null padded) */ case 'A': /* arbitrary binary string (ASCII space padded) */ case 'Z': /* null terminated string */ if (plen >= len) { rb_str_buf_cat(res, ptr, len if (p[-1] == '*' && type == 'Z') rb_str_buf_cat(res, nul10, 1 } else { rb_str_buf_cat(res, ptr, plen len -= plen; while (len >= 10) { rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10 len -= 10; } rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len } break; #define castchar(from) (char)((from) & 0xff) case 'b': /* bit string (ascending) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len - plen + 1)/2; len = plen; } for (i=0; i++ < len; ptr++) { if (*ptr & 1) byte |= 128; if (i & 7) byte >>= 1; else { char c = castchar(byte rb_str_buf_cat(res, &c, 1 byte = 0; } } if (len & 7) { char c; byte >>= 7 - (len & 7 c = castchar(byte rb_str_buf_cat(res, &c, 1 } len = j; goto grow; } break; case 'B': /* bit string (descending) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len - plen + 1)/2; len = plen; } for (i=0; i++ < len; ptr++) { byte |= *ptr & 1; if (i & 7) byte <<= 1; else { char c = castchar(byte rb_str_buf_cat(res, &c, 1 byte = 0; } } if (len & 7) { char c; byte <<= 7 - (len & 7 c = castchar(byte rb_str_buf_cat(res, &c, 1 } len = j; goto grow; } break; case 'h': /* hex string (low nibble first) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len + 1) / 2 - (plen + 1) / 2; len = plen; } for (i=0; i++ < len; ptr++) { if (ISALPHA(*ptr)) byte |= (((*ptr & 15) + 9) & 15) << 4; else byte |= (*ptr & 15) << 4; if (i & 1) byte >>= 4; else { char c = castchar(byte rb_str_buf_cat(res, &c, 1 byte = 0; } } if (len & 1) { char c = castchar(byte rb_str_buf_cat(res, &c, 1 } len = j; goto grow; } break; case 'H': /* hex string (high nibble first) */ { int byte = 0; long i, j = 0; if (len > plen) { j = (len + 1) / 2 - (plen + 1) / 2; len = plen; } for (i=0; i++ < len; ptr++) { if (ISALPHA(*ptr)) byte |= ((*ptr & 15) + 9) & 15; else byte |= *ptr & 15; if (i & 1) byte <<= 4; else { char c = castchar(byte rb_str_buf_cat(res, &c, 1 byte = 0; } } if (len & 1) { char c = castchar(byte rb_str_buf_cat(res, &c, 1 } len = j; goto grow; } break; } break; case 'c': /* signed char */ case 'C': /* unsigned char */ integer_size = 1; bigendian_p = BIGENDIAN_P( /* not effective */ goto pack_integer; case 's': /* s for int16_t, s! for signed short */ integer_size = NATINT_LEN(short, 2 bigendian_p = BIGENDIAN_P( goto pack_integer; case 'S': /* S for uint16_t, S! for unsigned short */ integer_size = NATINT_LEN(short, 2 bigendian_p = BIGENDIAN_P( goto pack_integer; case 'i': /* i and i! for signed int */ integer_size = (int)sizeof(int bigendian_p = BIGENDIAN_P( goto pack_integer; case 'I': /* I and I! for unsigned int */ integer_size = (int)sizeof(int bigendian_p = BIGENDIAN_P( goto pack_integer; case 'l': /* l for int32_t, l! for signed long */ integer_size = NATINT_LEN(long, 4 bigendian_p = BIGENDIAN_P( goto pack_integer; case 'L': /* L for uint32_t, L! for unsigned long */ integer_size = NATINT_LEN(long, 4 bigendian_p = BIGENDIAN_P( goto pack_integer; case 'q': /* q for int64_t, q! for signed long long */ integer_size = NATINT_LEN_Q; bigendian_p = BIGENDIAN_P( goto pack_integer; case 'Q': /* Q for uint64_t, Q! for unsigned long long */ integer_size = NATINT_LEN_Q; bigendian_p = BIGENDIAN_P( goto pack_integer; case 'j': /* j for intptr_t */ integer_size = sizeof(intptr_t bigendian_p = BIGENDIAN_P( goto pack_integer; case 'J': /* J for uintptr_t */ integer_size = sizeof(uintptr_t bigendian_p = BIGENDIAN_P( goto pack_integer; case 'n': /* 16 bit (2 bytes) integer (network byte-order) */ integer_size = 2; bigendian_p = 1; goto pack_integer; case 'N': /* 32 bit (4 bytes) integer (network byte-order) */ integer_size = 4; bigendian_p = 1; goto pack_integer; case 'v': /* 16 bit (2 bytes) integer (VAX byte-order) */ integer_size = 2; bigendian_p = 0; goto pack_integer; case 'V': /* 32 bit (4 bytes) integer (VAX byte-order) */ integer_size = 4; bigendian_p = 0; goto pack_integer; pack_integer: if (explicit_endian) { bigendian_p = explicit_endian == '>'; } if (integer_size > MAX_INTEGER_PACK_SIZE) rb_bug("unexpected intger size for pack: %d", integer_size while (len-- > 0) { char intbuf[MAX_INTEGER_PACK_SIZE]; from = NEXTFROM; rb_integer_pack(from, intbuf, integer_size, 1, 0, INTEGER_PACK_2COMP | (bigendian_p ? INTEGER_PACK_BIG_ENDIAN : INTEGER_PACK_LITTLE_ENDIAN) rb_str_buf_cat(res, intbuf, integer_size } break; case 'f': /* single precision float in native format */ case 'F': /* ditto */ while (len-- > 0) { float f; from = NEXTFROM; f = (float)RFLOAT_VALUE(rb_to_float(from) rb_str_buf_cat(res, (char*)&f, sizeof(float) } break; case 'e': /* single precision float in VAX byte-order */ while (len-- > 0) { FLOAT_CONVWITH(tmp from = NEXTFROM; tmp.f = (float)RFLOAT_VALUE(rb_to_float(from) HTOVF(tmp rb_str_buf_cat(res, tmp.buf, sizeof(float) } break; case 'E': /* double precision float in VAX byte-order */ while (len-- > 0) { DOUBLE_CONVWITH(tmp from = NEXTFROM; tmp.d = RFLOAT_VALUE(rb_to_float(from) HTOVD(tmp rb_str_buf_cat(res, tmp.buf, sizeof(double) } break; case 'd': /* double precision float in native format */ case 'D': /* ditto */ while (len-- > 0) { double d; from = NEXTFROM; d = RFLOAT_VALUE(rb_to_float(from) rb_str_buf_cat(res, (char*)&d, sizeof(double) } break; case 'g': /* single precision float in network byte-order */ while (len-- > 0) { FLOAT_CONVWITH(tmp from = NEXTFROM; tmp.f = (float)RFLOAT_VALUE(rb_to_float(from) HTONF(tmp rb_str_buf_cat(res, tmp.buf, sizeof(float) } break; case 'G': /* double precision float in network byte-order */ while (len-- > 0) { DOUBLE_CONVWITH(tmp from = NEXTFROM; tmp.d = RFLOAT_VALUE(rb_to_float(from) HTOND(tmp rb_str_buf_cat(res, tmp.buf, sizeof(double) } break; case 'x': /* null byte */ grow: while (len >= 10) { rb_str_buf_cat(res, nul10, 10 len -= 10; } rb_str_buf_cat(res, nul10, len break; case 'X': /* back up byte */ shrink: plen = RSTRING_LEN(res if (plen < len) rb_raise(rb_eArgError, "X outside of string" rb_str_set_len(res, plen - len break; case '@': /* null fill to absolute position */ len -= RSTRING_LEN(res if (len > 0) goto grow; len = -len; if (len > 0) goto shrink; break; case '%': rb_raise(rb_eArgError, "%% is not supported" break; case 'U': /* Unicode character */ while (len-- > 0) { SIGNED_VALUE l; char buf[8]; int le; from = NEXTFROM; from = rb_to_int(from l = NUM2LONG(from if (l < 0) { rb_raise(rb_eRangeError, "pack(U): value out of range" } le = rb_uv_to_utf8(buf, l rb_str_buf_cat(res, (char*)buf, le } break; case 'u': /* uuencoded string */ case 'm': /* base64 encoded string */ from = NEXTFROM; StringValue(from ptr = RSTRING_PTR(from plen = RSTRING_LEN(from if (len == 0 && type == 'm') { encodes(res, ptr, plen, type, 0 ptr += plen; break; } if (len <= 2) len = 45; else if (len > 63 && type == 'u') len = 63; else len = len / 3 * 3; while (plen > 0) { long todo; if (plen > len) todo = len; else todo = plen; encodes(res, ptr, todo, type, 1 plen -= todo; ptr += todo; } break; case 'M': /* quoted-printable encoded string */ from = rb_obj_as_string(NEXTFROM if (len <= 1) len = 72; qpencode(res, from, len break; case 'P': /* pointer to packed byte string */ from = THISFROM; if (!NIL_P(from)) { StringValue(from if (RSTRING_LEN(from) < len) { rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)", RSTRING_LEN(from), len } } len = 1; /* FALL THROUGH */ case 'p': /* pointer to string */ while (len-- > 0) { char *t; from = NEXTFROM; if (NIL_P(from)) { t = 0; } else { t = StringValuePtr(from rb_obj_taint(from } if (!associates) { associates = rb_ary_new( } rb_ary_push(associates, from rb_str_buf_cat(res, (char*)&t, sizeof(char*) } break; case 'w': /* BER compressed integer */ while (len-- > 0) { VALUE buf = rb_str_new(0, 0 size_t numbytes; int sign; char *cp; from = NEXTFROM; from = rb_to_int(from numbytes = rb_absint_numwords(from, 7, NULL if (numbytes == 0) numbytes = 1; buf = rb_str_new(NULL, numbytes sign = rb_integer_pack(from, RSTRING_PTR(buf), RSTRING_LEN(buf), 1, 1, INTEGER_PACK_BIG_ENDIAN if (sign < 0) rb_raise(rb_eArgError, "can't compress negative numbers" if (sign == 2) rb_bug("buffer size problem?" cp = RSTRING_PTR(buf while (1 < numbytes) { *cp |= 0x80; cp++; numbytes--; } rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf) } break; default: { char unknown[5]; if (ISPRINT(type)) { unknown[0] = type; unknown[1] = '\0'; } else { snprintf(unknown, sizeof(unknown), "\\x%.2x", type & 0xff } rb_warning("unknown pack directive '%s' in '% "PRIsVALUE"'", unknown, fmt break; } } } if (associates) { str_associate(res, associates } OBJ_INFECT(res, fmt switch (enc_info) { case 1: ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT break; case 2: rb_enc_set_index(res, rb_utf8_encindex() break; default: /* do nothing, keep ASCII-8BIT */ break; } return res; }

permutation { |p| block } → ary Show source

permutation → Enumerator

permutation(n) { |p| block } → ary

permutation(n) → Enumerator

当用块调用时,产生n数组元素的所有长度排列,然后返回数组本身。

如果n未指定,则产生所有元素的所有排列。

实现不能保证排列的顺序。

如果没有给出块,则返回一个枚举器。

例子:

a = [1, 2, 3] a.permutation.to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] a.permutation(1).to_a #=> [[1],[2],[3]] a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]] a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]] a.permutation(0).to_a #=> [[]] # one permutation of length 0 a.permutation(4).to_a #=> [] # no permutations of length 4

static VALUE rb_ary_permutation(int argc, VALUE *argv, VALUE ary) { VALUE num; long r, n, i; n = RARRAY_LEN(ary /* Array length */ RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size /* Return enumerator if no block */ rb_scan_args(argc, argv, "01", &num r = NIL_P(num) ? n : NUM2LONG(num /* Permutation size from argument */ if (r < 0 || n < r) { /* no permutations: yield nothing */ } else if (r == 0) { /* exactly one permutation: the zero-length array */ rb_yield(rb_ary_new2(0) } else if (r == 1) { /* this is a special, easy case */ for (i = 0; i < RARRAY_LEN(ary i++) { rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)) } } else { /* this is the general case */ volatile VALUE t0; long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)) char *used = (char*)(p + r VALUE ary0 = ary_make_shared_copy(ary /* private defensive copy of ary */ RBASIC_CLEAR_CLASS(ary0 MEMZERO(used, char, n /* initialize array */ permute0(n, r, p, used, ary0 /* compute and yield permutations */ ALLOCV_END(t0 RBASIC_SET_CLASS_RAW(ary0, rb_cArray } return ary; }

pop → obj or nil Show source

pop(n) → new_ary

从self中移除最后一个元素并返回它,如果数组为空,则返回nil。

如果给出数字n,就像array.slice!( - n,n)一样返回最后n个元素的数组(或更少)。 请参阅#push获取相反的效果。

a = [ "a", "b", "c", "d" ] a.pop #=> "d" a.pop(2) #=> ["b", "c"] a #=> ["a"]

static VALUE rb_ary_pop_m(int argc, VALUE *argv, VALUE ary) { VALUE result; if (argc == 0) { return rb_ary_pop(ary } rb_ary_modify_check(ary result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST ARY_INCREASE_LEN(ary, -RARRAY_LEN(result) return result; }

product(other_ary, ...) → new_ary Show source

product(other_ary, ...) { |p| block } → ary

返回所有数组中所有元素组合的数组。

返回数组的长度是长度self和参数数组的乘积。

如果给定一个块,结果将产生所有组合并返回self

[1,2,3].product([4,5]) #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]] [1,2].product([1,2]) #=> [[1,1],[1,2],[2,1],[2,2]] [1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6], # [2,3,5],[2,3,6],[2,4,5],[2,4,6]] [1,2].product() #=> [[1],[2]] [1,2].product([]) #=> []

static VALUE rb_ary_product(int argc, VALUE *argv, VALUE ary) { int n = argc+1; /* How many arrays we're operating on */ volatile VALUE t0 = tmpary(n volatile VALUE t1 = tmpbuf(n, sizeof(int) VALUE *arrays = RARRAY_PTR(t0 /* The arrays we're computing the product of */ int *counters = (int*)RSTRING_PTR(t1 /* The current position in each one */ VALUE result = Qnil; /* The array we'll be returning, when no block given */ long i,j; long resultlen = 1; RBASIC_CLEAR_CLASS(t0 RBASIC_CLEAR_CLASS(t1 /* initialize the arrays of arrays */ ARY_SET_LEN(t0, n arrays[0] = ary; for (i = 1; i < n; i++) arrays[i] = Qnil; for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1] /* initialize the counters for the arrays */ for (i = 0; i < n; i++) counters[i] = 0; /* Otherwise, allocate and fill in an array of results */ if (rb_block_given_p()) { /* Make defensive copies of arrays; exit if any is empty */ for (i = 0; i < n; i++) { if (RARRAY_LEN(arrays[i]) == 0) goto done; arrays[i] = ary_make_shared_copy(arrays[i] } } else { /* Compute the length of the result array; return [] if any is empty */ for (i = 0; i < n; i++) { long k = RARRAY_LEN(arrays[i] if (k == 0) { result = rb_ary_new2(0 goto done; } if (MUL_OVERFLOW_LONG_P(resultlen, k)) rb_raise(rb_eRangeError, "too big to product" resultlen *= k; } result = rb_ary_new2(resultlen } for (;;) { int m; /* fill in one subarray */ VALUE subarray = rb_ary_new2(n for (j = 0; j < n; j++) { rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]) } /* put it on the result array */ if (NIL_P(result)) { FL_SET(t0, FL_USER5 rb_yield(subarray if (! FL_TEST(t0, FL_USER5)) { rb_raise(rb_eRuntimeError, "product reentered" } else { FL_UNSET(t0, FL_USER5 } } else { rb_ary_push(result, subarray } /* * Increment the last counter. If it overflows, reset to 0 * and increment the one before it. */ m = n-1; counters[m]++; while (counters[m] == RARRAY_LEN(arrays[m])) { counters[m] = 0; /* If the first counter overflows, we are done */ if (--m < 0) goto done; counters[m]++; } } done: tmpary_discard(t0 tmpbuf_discard(t1 return NIL_P(result) ? ary : result; }

push(obj, ... ) → ary Show source

追加 - 将给定的对象推到该数组的末尾。该表达式返回数组本身,因此可以将几个附加链接在一起。另请参阅#pop,以获得相反的效果。

a = [ "a", "b", "c" ] a.push("d", "e", "f") #=> ["a", "b", "c", "d", "e", "f"] [1, 2, 3].push(4).push(5) #=> [1, 2, 3, 4, 5]

static VALUE rb_ary_push_m(int argc, VALUE *argv, VALUE ary) { return rb_ary_cat(ary, argv, argc }

rassoc(obj) → element_ary or nil Show source

搜索其元素也是数组的数组。

使用obj。==将obj与每个包含数组的第二个元素进行比较。

返回匹配的第一个包含的数组obj

另见#assoc。

a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ] a.rassoc("two") #=> [2, "two"] a.rassoc("four") #=> nil

VALUE rb_ary_rassoc(VALUE ary, VALUE value) { long i; VALUE v; for (i = 0; i < RARRAY_LEN(ary ++i) { v = RARRAY_AREF(ary, i if (RB_TYPE_P(v, T_ARRAY) && RARRAY_LEN(v) > 1 && rb_equal(RARRAY_AREF(v, 1), value)) return v; } return Qnil; }

reject {|item| block } → new_ary Show source

reject → Enumerator

返回一个新数组self,其中包含给定块所不包含的项目true。未拒绝元素的排序被保留。

另见#delete_if

如果没有给出块,则返回一个枚举器。

static VALUE rb_ary_reject(VALUE ary) { VALUE rejected_ary; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length rejected_ary = rb_ary_new( ary_reject(ary, rejected_ary return rejected_ary; }

reject! { |item| block } → ary or nil Show source

reject! → Enumerator

如果没有进行更改,则删除块评估为true的每个self元素返回nil。

每次调用该块时,该阵列可能不会立即更改。

另请参阅Enumerable#reject和#delete_if。

如果没有给出块,则返回一个枚举器。

static VALUE rb_ary_reject_bang(VALUE ary) { RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length return ary_reject_bang(ary }

repeated_combination(n) { |c| block } → ary Show source

repeated_combination(n) → Enumerator

当用块调用时,产生n数组中元素长度的所有重复组合,然后返回数组本身。

该实现不保证重复组合的产生顺序。

如果没有给出块,则返回一个枚举器。

例子:

a = [1, 2, 3] a.repeated_combination(1).to_a #=> [[1], [2], [3]] a.repeated_combination(2).to_a #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]] a.repeated_combination(3).to_a #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3], # [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]] 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], # [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3], # [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]] a.repeated_combination(0).to_a #=> [[]] # one combination of length 0

static VALUE rb_ary_repeated_combination(VALUE ary, VALUE num) { long n, i, len; n = NUM2LONG(num /* Combination size from argument */ RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_combination_size /* Return enumerator if no block */ len = RARRAY_LEN(ary if (n < 0) { /* yield nothing */ } else if (n == 0) { rb_yield(rb_ary_new2(0) } else if (n == 1) { for (i = 0; i < RARRAY_LEN(ary i++) { rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)) } } else if (len == 0) { /* yield nothing */ } else { volatile VALUE t0; long *p = ALLOCV_N(long, t0, n VALUE ary0 = ary_make_shared_copy(ary /* private defensive copy of ary */ RBASIC_CLEAR_CLASS(ary0 rcombinate0(len, n, p, n, ary0 /* compute and yield repeated combinations */ ALLOCV_END(t0 RBASIC_SET_CLASS_RAW(ary0, rb_cArray } return ary; }

repeated_permutation(n) { |p| block } → ary Show source

repeated_permutation(n) → Enumerator

当用块调用时,产生n数组元素长度的所有重复排列,然后返回数组本身。

该实现不保证重复排列的顺序。

如果没有给出块,则返回一个枚举器。

例子:

a = [1, 2] a.repeated_permutation(1).to_a #=> [[1], [2]] a.repeated_permutation(2).to_a #=> [[1,1],[1,2],[2,1],[2,2]] a.repeated_permutation(3).to_a #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2], # [2,1,1],[2,1,2],[2,2,1],[2,2,2]] a.repeated_permutation(0).to_a #=> [[]] # one permutation of length 0

static VALUE rb_ary_repeated_permutation(VALUE ary, VALUE num) { long r, n, i; n = RARRAY_LEN(ary /* Array length */ RETURN_SIZED_ENUMERATOR(ary, 1, &num, rb_ary_repeated_permutation_size /* Return Enumerator if no block */ r = NUM2LONG(num /* Permutation size from argument */ if (r < 0) { /* no permutations: yield nothing */ } else if (r == 0) { /* exactly one permutation: the zero-length array */ rb_yield(rb_ary_new2(0) } else if (r == 1) { /* this is a special, easy case */ for (i = 0; i < RARRAY_LEN(ary i++) { rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)) } } else { /* this is the general case */ volatile VALUE t0; long *p = ALLOCV_N(long, t0, r VALUE ary0 = ary_make_shared_copy(ary /* private defensive copy of ary */ RBASIC_CLEAR_CLASS(ary0 rpermute0(n, r, p, ary0 /* compute and yield repeated permutations */ ALLOCV_END(t0 RBASIC_SET_CLASS_RAW(ary0, rb_cArray } return ary; }

replace(other_ary) → ary Show source

用other_ary的内容替换self的内容,如有必要,截断或扩展。

a = [ "a", "b", "c", "d", "e" ] a.replace([ "x", "y", "z" ]) #=> ["x", "y", "z"] a #=> ["x", "y", "z"]

VALUE rb_ary_replace(VALUE copy, VALUE orig) { rb_ary_modify_check(copy orig = to_ary(orig if (copy == orig) return copy; if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) { VALUE shared = 0; if (ARY_OWNS_HEAP_P(copy)) { RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)) } else if (ARY_SHARED_P(copy)) { shared = ARY_SHARED(copy FL_UNSET_SHARED(copy } FL_SET_EMBED(copy ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig) if (shared) { rb_ary_decrement_share(shared } ARY_SET_LEN(copy, RARRAY_LEN(orig) } else { VALUE shared = ary_make_shared(orig if (ARY_OWNS_HEAP_P(copy)) { RARRAY_PTR_USE(copy, ptr, ruby_sized_xfree(ptr, ARY_HEAP_SIZE(copy)) } else { rb_ary_unshare_safe(copy } FL_UNSET_EMBED(copy ARY_SET_PTR(copy, RARRAY_CONST_PTR(orig) ARY_SET_LEN(copy, RARRAY_LEN(orig) rb_ary_set_shared(copy, shared } return copy; }

reverse → new_ary Show source

以相反顺序返回包含self元素的新数组。

[ "a", "b", "c" ].reverse #=> ["c", "b", "a"] [ 1 ].reverse #=> [1]

static VALUE rb_ary_reverse_m(VALUE ary) { long len = RARRAY_LEN(ary VALUE dup = rb_ary_new2(len if (len > 0) { const VALUE *p1 = RARRAY_CONST_PTR(ary VALUE *p2 = (VALUE *)RARRAY_CONST_PTR(dup) + len - 1; do *p2-- = *p1++; while (--len > 0 } ARY_SET_LEN(dup, RARRAY_LEN(ary) return dup; }

reverse! → ary Show source

反转self到位。

a = [ "a", "b", "c" ] a.reverse! #=> ["c", "b", "a"] a #=> ["c", "b", "a"]

static VALUE rb_ary_reverse_bang(VALUE ary) { return rb_ary_reverse(ary }

reverse_each { |item| block } → ary Show source

reverse_each → Enumerator

与#each相同,但self以相反的顺序遍历。

a = [ "a", "b", "c" ] a.reverse_each {|x| print x, " " }

produces:

c b a

static VALUE rb_ary_reverse_each(VALUE ary) { long len; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length len = RARRAY_LEN(ary while (len--) { long nlen; rb_yield(RARRAY_AREF(ary, len) nlen = RARRAY_LEN(ary if (nlen < len) { len = nlen; } } return ary; }

rindex(obj) → int or nil Show source

rindex { |item| block } → int or nil

rindex → Enumerator

将self ==中最后一个对象的索引返回给obj。

如果给出的是块而不是参数,则返回块返回的第一个对象的索引true,从最后一个对象开始。

如果未找到匹配项,则返回nil

另见#index。

如果块和参数均未给出,则返回枚举器。

a = [ "a", "b", "b", "b", "c" ] a.rindex("b") #=> 3 a.rindex("z") #=> nil a.rindex { |x| x == "b" } #=> 3

static VALUE rb_ary_rindex(int argc, VALUE *argv, VALUE ary) { const VALUE *ptr; VALUE val; long i = RARRAY_LEN(ary), len; if (argc == 0) { RETURN_ENUMERATOR(ary, 0, 0 while (i--) { if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return LONG2NUM(i if (i > (len = RARRAY_LEN(ary))) { i = len; } } return Qnil; } rb_check_arity(argc, 0, 1 val = argv[0]; if (rb_block_given_p()) rb_warn("given block not used" ptr = RARRAY_CONST_PTR(ary while (i--) { VALUE e = ptr[i]; switch (rb_equal_opt(e, val)) { case Qundef: if (!rb_equal(e, val)) break; case Qtrue: return LONG2NUM(i case Qfalse: continue; } if (i > (len = RARRAY_LEN(ary))) { i = len; } ptr = RARRAY_CONST_PTR(ary } return Qnil; }

rotate(count=1) → new_ary Show source

通过旋转self来返回一个新数组,以便count中的元素是新数组的第一个元素。

如果count为负,那么它会以相反的方向旋转,从self的末尾开始,其中-1是最后一个元素。

a = [ "a", "b", "c", "d" ] a.rotate #=> ["b", "c", "d", "a"] a #=> ["a", "b", "c", "d"] a.rotate(2) #=> ["c", "d", "a", "b"] a.rotate(-3) #=> ["b", "c", "d", "a"]

static VALUE rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary) { VALUE rotated; const VALUE *ptr; long len, cnt = 1; switch (argc) { case 1: cnt = NUM2LONG(argv[0] case 0: break; default: rb_scan_args(argc, argv, "01", NULL } len = RARRAY_LEN(ary rotated = rb_ary_new2(len if (len > 0) { cnt = rotate_count(cnt, len ptr = RARRAY_CONST_PTR(ary len -= cnt; ary_memcpy(rotated, 0, len, ptr + cnt ary_memcpy(rotated, len, cnt, ptr } ARY_SET_LEN(rotated, RARRAY_LEN(ary) return rotated; }

rotate!(count=1) → ary Show source

旋转自己的位置,以便计数中的元素先出现,然后返回自身。

如果count是负数,则它以相反的方向旋转,从-1最后一个元素的数组末尾开始。

a = [ "a", "b", "c", "d" ] a.rotate! #=> ["b", "c", "d", "a"] a #=> ["b", "c", "d", "a"] a.rotate!(2) #=> ["d", "a", "b", "c"] a.rotate!(-3) #=> ["a", "b", "c", "d"]

static VALUE rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary) { long n = 1; switch (argc) { case 1: n = NUM2LONG(argv[0] case 0: break; default: rb_scan_args(argc, argv, "01", NULL } rb_ary_rotate(ary, n return ary; }

sample → obj Show source

sample(random: rng) → obj

sample(n) → new_ary

sample(n, random: rng) → new_ary

从数组中选择一个随机元素或n个随机元素。

通过在数组中使用随机和唯一索引来选择元素,以确保元素不会重复,除非数组已经包含重复元素。

如果数组为空,则第一个窗体返回nil,第二个窗体返回一个空数组。

可选rng参数将用作随机数生成器。

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

static VALUE rb_ary_sample(int argc, VALUE *argv, VALUE ary) { VALUE nv, result; VALUE opts, randgen = rb_cRandom; long n, len, i, j, k, idx[10]; long rnds[numberof(idx)]; if (OPTHASH_GIVEN_P(opts)) { VALUE rnd; ID keyword_ids[1]; keyword_ids[0] = id_random; rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd if (rnd != Qundef) { randgen = rnd; } } len = RARRAY_LEN(ary if (argc == 0) { if (len < 2) i = 0; else i = RAND_UPTO(len return rb_ary_elt(ary, i } rb_scan_args(argc, argv, "1", &nv n = NUM2LONG(nv if (n < 0) rb_raise(rb_eArgError, "negative sample number" if (n > len) n = len; if (n <= numberof(idx)) { for (i = 0; i < n; ++i) { rnds[i] = RAND_UPTO(len - i } } k = len; len = RARRAY_LEN(ary if (len < k && n <= numberof(idx)) { for (i = 0; i < n; ++i) { if (rnds[i] >= len) return rb_ary_new_capa(0 } } if (n > len) n = len; switch (n) { case 0: return rb_ary_new_capa(0 case 1: i = rnds[0]; return rb_ary_new_from_values(1, &RARRAY_AREF(ary, i) case 2: i = rnds[0]; j = rnds[1]; if (j >= i) j++; return rb_ary_new_from_args(2, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j) case 3: i = rnds[0]; j = rnds[1]; k = rnds[2]; { long l = j, g = i; if (j >= i) l = i, g = ++j; if (k >= l && (++k >= g)) ++k; } return rb_ary_new_from_args(3, RARRAY_AREF(ary, i), RARRAY_AREF(ary, j), RARRAY_AREF(ary, k) } if (n <= numberof(idx)) { long sorted[numberof(idx)]; sorted[0] = idx[0] = rnds[0]; for (i=1; i<n; i++) { k = rnds[i]; for (j = 0; j < i; ++j) { if (k < sorted[j]) break; ++k; } memmove(&sorted[j+1], &sorted[j], sizeof(sorted[0])*(i-j) sorted[j] = idx[i] = k; } result = rb_ary_new_capa(n RARRAY_PTR_USE(result, ptr_result, { for (i=0; i<n; i++) { ptr_result[i] = RARRAY_AREF(ary, idx[i] } } } else { result = rb_ary_dup(ary RBASIC_CLEAR_CLASS(result RB_GC_GUARD(ary RARRAY_PTR_USE(result, ptr_result, { for (i=0; i<n; i++) { j = RAND_UPTO(len-i) + i; nv = ptr_result[j]; ptr_result[j] = ptr_result[i]; ptr_result[i] = nv; } } RBASIC_SET_CLASS_RAW(result, rb_cArray } ARY_SET_LEN(result, n return result; }

select { |item| block } → new_ary Show source

select → Enumerator

返回一个新数组,其中包含给定块返回true值的所有艺术元素。

如果没有给出块,则返回一个枚举器。

[1,2,3,4,5].select { |num| num.even? } #=> [2, 4] a = %w{ a b c d e f } a.select { |v| v =~ /[aeiou]/ } #=> ["a", "e"]

另请参阅Enumerable#select。

static VALUE rb_ary_select(VALUE ary) { VALUE result; long i; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length result = rb_ary_new2(RARRAY_LEN(ary) for (i = 0; i < RARRAY_LEN(ary i++) { if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) { rb_ary_push(result, rb_ary_elt(ary, i) } } return result; }

select! {|item| block } → ary or nil Show source

select! → Enumerator

调用传入的连续元素的给定块self,删除块返回false值的元素。

每次调用该块时,该阵列可能不会立即更改。

如果进行了更改,则会返回self,否则返回nil

另见#keep_if

如果没有给出块,则返回一个枚举器。

static VALUE rb_ary_select_bang(VALUE ary) { struct select_bang_arg args; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length rb_ary_modify(ary args.ary = ary; args.len[0] = args.len[1] = 0; return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args }

shelljoin → string Show source

从参数列表构建一个命令行字符串,用于array加入为Bourne shell转义并由空格分隔的所有元素。

有关详细信息,请参阅Shellwords#shelljoin。

# File lib/shellwords.rb, line 227 def shelljoin Shellwords.join(self) end

shift → obj or nil Show source

shift(n) → new_ary

移除自身的第一个元素并将其返回(将所有其他元素向下移动一个)。 如果数组为空,则返回nil。

如果给出数字n,就像array.slice!(0,n)一样返回前n个元素(或更少)的数组。 只包含剩余元素的ary,不包括转移到new_ary的元素。 请参阅#unshift以获得相反的效果。

args = [ "-m", "-q", "filename" ] args.shift #=> "-m" args #=> ["-q", "filename"] args = [ "-m", "-q", "filename" ] args.shift(2) #=> ["-m", "-q"] args #=> ["filename"]

static VALUE rb_ary_shift_m(int argc, VALUE *argv, VALUE ary) { VALUE result; long n; if (argc == 0) { return rb_ary_shift(ary } rb_ary_modify_check(ary result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST n = RARRAY_LEN(result if (ARY_SHARED_P(ary)) { if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) { setup_occupied_shared: ary_mem_clear(ary, 0, n } ARY_INCREASE_PTR(ary, n } else { if (RARRAY_LEN(ary) < ARY_DEFAULT_SIZE) { RARRAY_PTR_USE(ary, ptr, { MEMMOVE(ptr, ptr+n, VALUE, RARRAY_LEN(ary)-n } /* WB: no new reference */ } else { ary_make_shared(ary goto setup_occupied_shared; } } ARY_INCREASE_LEN(ary, -n return result; }

shuffle → new_ary Show source

shuffle(random: rng) → new_ary

返回包含self混洗元素的新数组。

a = [ 1, 2, 3 ] #=> [1, 2, 3] a.shuffle #=> [2, 3, 1] a #=> [1, 2, 3]

可选rng参数将用作随机数生成器。

a.shuffle(random: Random.new(1)) #=> [1, 3, 2]

static VALUE rb_ary_shuffle(int argc, VALUE *argv, VALUE ary) { ary = rb_ary_dup(ary rb_ary_shuffle_bang(argc, argv, ary return ary; }

shuffle! → ary Show source

shuffle!(random: rng) → ary

self在适当位置混合元素。

a = [ 1, 2, 3 ] #=> [1, 2, 3] a.shuffle! #=> [2, 3, 1] a #=> [2, 3, 1]

可选rng参数将用作随机数生成器。

a.shuffle!(random: Random.new(1)) #=> [1, 3, 2]

static VALUE rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary) { VALUE opts, randgen = rb_cRandom; long i, len; if (OPTHASH_GIVEN_P(opts)) { VALUE rnd; ID keyword_ids[1]; keyword_ids[0] = id_random; rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd if (rnd != Qundef) { randgen = rnd; } } rb_check_arity(argc, 0, 0 rb_ary_modify(ary i = len = RARRAY_LEN(ary RARRAY_PTR_USE(ary, ptr, { while (i) { long j = RAND_UPTO(i VALUE tmp; if (len != RARRAY_LEN(ary) || ptr != RARRAY_CONST_PTR(ary)) { rb_raise(rb_eRuntimeError, "modified during shuffle" } tmp = ptr[--i]; ptr[i] = ptr[j]; ptr[j] = tmp; } } /* WB: no new reference */ return ary; }

size()

别名为:长度

slice(index) → obj or nil Show source

slice(start, length) → new_ary or nil

slice(range) → new_ary or nil

元素参考 - 返回索引处的元素,或返回从开始索引处开始并继续长度元素的子阵列,或者返回由索引范围指定的子阵列。

负数索引从数组末尾向后计数(-1是最后一个元素)。 对于开始和范围情况,起始索引就在元素之前。 此外,当元素范围的起始索引位于数组的末尾时,将返回一个空数组。

如果索引(或起始索引)超出范围,返回nil

a = [ "a", "b", "c", "d", "e" ] a[2] + a[0] + a[1] #=> "cab" a[6] #=> nil a[1, 2] #=> [ "b", "c" ] a[1..3] #=> [ "b", "c", "d" ] a[4..7] #=> [ "e" ] a[6..10] #=> nil a[-3, 3] #=> [ "c", "d", "e" ] # special cases a[5] #=> nil a[6, 1] #=> nil a[5, 1] #=> [] a[5..10] #=> []

VALUE rb_ary_aref(int argc, const VALUE *argv, VALUE ary) { VALUE arg; long beg, len; if (argc == 2) { beg = NUM2LONG(argv[0] len = NUM2LONG(argv[1] if (beg < 0) { beg += RARRAY_LEN(ary } return rb_ary_subseq(ary, beg, len } if (argc != 1) { rb_scan_args(argc, argv, "11", NULL, NULL } arg = argv[0]; /* special case - speeding up */ if (FIXNUM_P(arg)) { return rb_ary_entry(ary, FIX2LONG(arg) } /* check if idx is Range */ switch (rb_range_beg_len(arg, &beg, &len, RARRAY_LEN(ary), 0)) { case Qfalse: break; case Qnil: return Qnil; default: return rb_ary_subseq(ary, beg, len } return rb_ary_entry(ary, NUM2LONG(arg) }

slice!(index) → obj or nil Show source

slice!(start, length) → new_ary or nil

slice!(range) → new_ary or nil

删除由索引(可选直到长度元素)或范围给出的元素。

返回已删除的对象(或多个对象);如果索引超出范围,则返回nil。

a = [ "a", "b", "c" ] a.slice!(1) #=> "b" a #=> ["a", "c"] a.slice!(-1) #=> "c" a #=> ["a"] a.slice!(100) #=> nil a #=> ["a"]

static VALUE rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary) { VALUE arg1, arg2; long pos, len, orig_len; rb_ary_modify_check(ary if (argc == 2) { pos = NUM2LONG(argv[0] len = NUM2LONG(argv[1] delete_pos_len: if (len < 0) return Qnil; orig_len = RARRAY_LEN(ary if (pos < 0) { pos += orig_len; if (pos < 0) return Qnil; } else if (orig_len < pos) return Qnil; if (orig_len < pos + len) { len = orig_len - pos; } if (len == 0) return rb_ary_new2(0 arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos RBASIC_SET_CLASS(arg2, rb_obj_class(ary) rb_ary_splice(ary, pos, len, 0, 0 return arg2; } if (argc != 1) { /* error report */ rb_scan_args(argc, argv, "11", NULL, NULL } arg1 = argv[0]; if (!FIXNUM_P(arg1)) { switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) { case Qtrue: /* valid range */ goto delete_pos_len; case Qnil: /* invalid range */ return Qnil; default: /* not a range */ break; } } return rb_ary_delete_at(ary, NUM2LONG(arg1) }

sort → new_ary Show source

sort { |a, b| block } → new_ary

返回通过排序自身创建的新数组。

使用<=>操作员或使用可选代码块进行排序比较。

块必须实现a和b之间的比较,并返回一个小于0的整数,当b跟随a时,a和b相等时为0,或者当a跟随b时返回大于0的整数。

结果不能保证稳定。 当两个元素的比较返回0时,元素的顺序是不可预知的。

a = [ "d", "a", "e", "c", "b" ] a.sort #=> ["a", "b", "c", "d", "e"] a.sort { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]

另请参阅Enumerable#sort_by。

VALUE rb_ary_sort(VALUE ary) { ary = rb_ary_dup(ary rb_ary_sort_bang(ary return ary; }

sort! → ary Show source

sort! { |a, b| block } → ary

排序self

使用<=>操作员或使用可选代码块进行排序比较。

块必须实现a和b之间的比较,并返回一个小于0的整数,当b跟随a时,a和b相等时为0,或者当a跟随b时返回大于0的整数。

结果不能保证稳定。当两个元素的比较返回0时元素的顺序是不可预知的。

a = [ "d", "a", "e", "c", "b" ] a.sort! #=> ["a", "b", "c", "d", "e"] a.sort! { |x,y| y <=> x } #=> ["e", "d", "c", "b", "a"]

另请参阅Enumerable#sort_by。

VALUE rb_ary_sort_bang(VALUE ary) { rb_ary_modify(ary assert(!ARY_SHARED_P(ary) if (RARRAY_LEN(ary) > 1) { VALUE tmp = ary_make_substitution(ary /* only ary refers tmp */ struct ary_sort_data data; long len = RARRAY_LEN(ary RBASIC_CLEAR_CLASS(tmp data.ary = tmp; data.cmp_opt.opt_methods = 0; data.cmp_opt.opt_inited = 0; RARRAY_PTR_USE(tmp, ptr, { ruby_qsort(ptr, len, sizeof(VALUE), rb_block_given_p()?sort_1:sort_2, &data } /* WB: no new reference */ rb_ary_modify(ary if (ARY_EMBED_P(tmp)) { if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */ rb_ary_unshare(ary FL_SET_EMBED(ary } ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp) ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp) } else { if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) { FL_UNSET_SHARED(ary ARY_SET_CAPA(ary, RARRAY_LEN(tmp) } else { assert(!ARY_SHARED_P(tmp) if (ARY_EMBED_P(ary)) { FL_UNSET_EMBED(ary } else if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */ rb_ary_unshare(ary } else { ruby_sized_xfree((void *)ARY_HEAP_PTR(ary), ARY_HEAP_SIZE(ary) } ARY_SET_PTR(ary, RARRAY_CONST_PTR(tmp) ARY_SET_HEAP_LEN(ary, len ARY_SET_CAPA(ary, RARRAY_LEN(tmp) } /* tmp was lost ownership for the ptr */ FL_UNSET(tmp, FL_FREEZE FL_SET_EMBED(tmp ARY_SET_EMBED_LEN(tmp, 0 FL_SET(tmp, FL_FREEZE } /* tmp will be GC'ed. */ RBASIC_SET_CLASS_RAW(tmp, rb_cArray /* rb_cArray must be marked */ } return ary; }

sort_by! { |obj| block } → ary Show source

sort_by! → Enumerator

使用通过在给定块中映射自身中的值生成的一组密钥来对自己进行排序。

结果不能保证稳定。当两个键相等时,相应元素的顺序是不可预知的。

如果没有给出块,则返回一个枚举器。

另请参阅Enumerable#sort_by。

static VALUE rb_ary_sort_by_bang(VALUE ary) { VALUE sorted; RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length rb_ary_modify(ary sorted = rb_block_call(ary, rb_intern("sort_by"), 0, 0, sort_by_i, 0 rb_ary_replace(ary, sorted return ary; }

sum(init=0) → number Show source

sum(init=0) {|e| expr } → number

返回元素的总和。例如,e1,e2,e3.sum返回init + e1 + e2 + e3。

如果给出了一个块,则该块在添加之前应用于每个元素。

如果ary为空,则返回init

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

数组的(算术)平均值可以如下获得。

mean = ary.sum(0.0) / ary.length

通过显式初始化参数可以将此方法用于非数字对象。

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

但是,#join和#flatten比数组字符串和数组数组快。

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

#sum方法可能不会重新定义诸如Integer#+之类的“+”方法。

static VALUE rb_ary_sum(int argc, VALUE *argv, VALUE ary) { VALUE e, v, r; long i, n; int block_given; if (rb_scan_args(argc, argv, "01", &v) == 0) v = LONG2FIX(0 block_given = rb_block_given_p( if (RARRAY_LEN(ary) == 0) return v; n = 0; r = Qundef; for (i = 0; i < RARRAY_LEN(ary i++) { e = RARRAY_AREF(ary, i if (block_given) e = rb_yield(e if (FIXNUM_P(e)) { n += FIX2LONG(e /* should not overflow long type */ if (!FIXABLE(n)) { v = rb_big_plus(LONG2NUM(n), v n = 0; } } else if (RB_TYPE_P(e, T_BIGNUM)) v = rb_big_plus(e, v else if (RB_TYPE_P(e, T_RATIONAL)) { if (r == Qundef) r = e; else r = rb_rational_plus(r, e } else goto not_exact; } if (n != 0) v = rb_fix_plus(LONG2FIX(n), v if (r != Qundef) { /* r can be an Integer when mathn is loaded */ if (FIXNUM_P(r)) v = rb_fix_plus(r, v else if (RB_TYPE_P(r, T_BIGNUM)) v = rb_big_plus(r, v else v = rb_rational_plus(r, v } return v; not_exact: if (n != 0) v = rb_fix_plus(LONG2FIX(n), v if (r != Qundef) { /* r can be an Integer when mathn is loaded */ if (FIXNUM_P(r)) v = rb_fix_plus(r, v else if (RB_TYPE_P(r, T_BIGNUM)) v = rb_big_plus(r, v else v = rb_rational_plus(r, v } if (RB_FLOAT_TYPE_P(e)) { /* * Kahan-Babuska balancing compensated summation algorithm * See http://link.springer.com/article/10.1007/s00607-005-0139-x */ double f, c; f = NUM2DBL(v c = 0.0; goto has_float_value; for (; i < RARRAY_LEN(ary i++) { double x, t; e = RARRAY_AREF(ary, i if (block_given) e = rb_yield(e if (RB_FLOAT_TYPE_P(e)) has_float_value: x = RFLOAT_VALUE(e else if (FIXNUM_P(e)) x = FIX2LONG(e else if (RB_TYPE_P(e, T_BIGNUM)) x = rb_big2dbl(e else if (RB_TYPE_P(e, T_RATIONAL)) x = rb_num2dbl(e else goto not_float; t = f + x; if (fabs(f) >= fabs(x)) c += ((f - t) + x else c += ((x - t) + f f = t; } f += c; return DBL2NUM(f not_float: v = DBL2NUM(f } goto has_some_value; for (; i < RARRAY_LEN(ary i++) { e = RARRAY_AREF(ary, i if (block_given) e = rb_yield(e has_some_value: v = rb_funcall(v, idPLUS, 1, e } return v; }

take(n) → new_ary Show source

返回n数组中的第一个元素。

如果给出一个负数,则引发一个ArgumentError。

另见#drop

a = [1, 2, 3, 4, 5, 0] a.take(3) #=> [1, 2, 3]

static VALUE rb_ary_take(VALUE obj, VALUE n) { long len = NUM2LONG(n if (len < 0) { rb_raise(rb_eArgError, "attempt to take negative size" } return rb_ary_subseq(obj, 0, len }

take_while { |obj| block } → new_ary Show source

take_while → Enumerator

传递元件,直到块返回nilfalse,然后停止迭代并返回所有现有元件的阵列。

如果没有给出块,则返回一个枚举器。

另见#drop_while

a = [1, 2, 3, 4, 5, 0] a.take_while { |i| i < 3 } #=> [1, 2]

static VALUE rb_ary_take_while(VALUE ary) { long i; RETURN_ENUMERATOR(ary, 0, 0 for (i = 0; i < RARRAY_LEN(ary i++) { if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) break; } return rb_ary_take(ary, LONG2FIX(i) }

to_a → ary Show source

返回self

如果在Array的子​​类上调用,则将接收器转换为Array对象。

static VALUE rb_ary_to_a(VALUE ary) { if (rb_obj_class(ary) != rb_cArray) { VALUE dup = rb_ary_new2(RARRAY_LEN(ary) rb_ary_replace(dup, ary return dup; } return ary; }

to_ary → ary Show source

返回self

static VALUE rb_ary_to_ary_m(VALUE ary) { return ary; }

to_h → hash Show source

将解释ary的结果作为一[key, value]对数组返回。

[[:foo, :bar], [1, 2]].to_h # => {:foo => :bar, 1 => 2}

static VALUE rb_ary_to_h(VALUE ary) { long i; VALUE hash = rb_hash_new( for (i=0; i<RARRAY_LEN(ary i++) { const VALUE elt = rb_ary_elt(ary, i const VALUE key_value_pair = rb_check_array_type(elt if (NIL_P(key_value_pair)) { rb_raise(rb_eTypeError, "wrong element type %"PRIsVALUE" at %ld (expected array)", rb_obj_class(elt), i } if (RARRAY_LEN(key_value_pair) != 2) { rb_raise(rb_eArgError, "wrong array length at %ld (expected 2, was %ld)", i, RARRAY_LEN(key_value_pair) } rb_hash_aset(hash, RARRAY_AREF(key_value_pair, 0), RARRAY_AREF(key_value_pair, 1) } return hash; }

to_s()

别名为:检查

transpose → new_ary Show source

假设self是一个数组数组并转换行和列。

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

如果子阵列的长度不匹配,则会引发IndexError。

static VALUE rb_ary_transpose(VALUE ary) { long elen = -1, alen, i, j; VALUE tmp, result = 0; alen = RARRAY_LEN(ary if (alen == 0) return rb_ary_dup(ary for (i=0; i<alen; i++) { tmp = to_ary(rb_ary_elt(ary, i) if (elen < 0) { /* first element */ elen = RARRAY_LEN(tmp result = rb_ary_new2(elen for (j=0; j<elen; j++) { rb_ary_store(result, j, rb_ary_new2(alen) } } else if (elen != RARRAY_LEN(tmp)) { rb_raise(rb_eIndexError, "element size differs (%ld should be %ld)", RARRAY_LEN(tmp), elen } for (j=0; j<elen; j++) { rb_ary_store(rb_ary_elt(result, j), i, rb_ary_elt(tmp, j) } } return result; }

uniq → new_ary Show source

uniq { |item| ... } → new_ary

通过删除重复值来返回新数组。

如果给出了一个块,它将使用块的返回值进行比较。

它使用hash和eql比较值?提高效率的方法。

self 按顺序遍历,并保持第一次出现。

a = [ "a", "a", "b", "b", "c" ] a.uniq # => ["a", "b", "c"] b = [["student","sam"], ["student","george"], ["teacher","matz"]] b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]

static VALUE rb_ary_uniq(VALUE ary) { VALUE hash, uniq; if (RARRAY_LEN(ary) <= 1) return rb_ary_dup(ary if (rb_block_given_p()) { hash = ary_make_hash_by(ary uniq = rb_hash_values(hash } else { hash = ary_make_hash(ary uniq = rb_hash_values(hash } RBASIC_SET_CLASS(uniq, rb_obj_class(ary) ary_recycle_hash(hash return uniq; }

uniq! → ary or nil Show source

uniq! { |item| ... } → ary or nil

self中删除重复的元素。

如果给出了一个块,它将使用块的返回值进行比较。

它使用hash和eql比较值?提高效率的方法。

self 按顺序遍历,并保持第一次出现。

如果没有更改,则返回nil(即没有找到重复项)。

a = [ "a", "a", "b", "b", "c" ] a.uniq! # => ["a", "b", "c"] b = [ "a", "b", "c" ] b.uniq! # => nil c = [["student","sam"], ["student","george"], ["teacher","matz"]] c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]

static VALUE rb_ary_uniq_bang(VALUE ary) { VALUE hash; long hash_size; rb_ary_modify_check(ary if (RARRAY_LEN(ary) <= 1) return Qnil; if (rb_block_given_p()) hash = ary_make_hash_by(ary else hash = ary_make_hash(ary hash_size = RHASH_SIZE(hash if (RARRAY_LEN(ary) == hash_size) { return Qnil; } rb_ary_modify_check(ary ARY_SET_LEN(ary, 0 if (ARY_SHARED_P(ary) && !ARY_EMBED_P(ary)) { rb_ary_unshare(ary FL_SET_EMBED(ary } ary_resize_capa(ary, hash_size st_foreach(rb_hash_tbl_raw(hash), push_value, ary ary_recycle_hash(hash return ary; }

unshift(obj, ...) → ary Show source

向前移动物体,向上移动其他元素。 另请参阅#shift以获得相反的效果。

a = [ "b", "c", "d" ] a.unshift("a") #=> ["a", "b", "c", "d"] a.unshift(1, 2) #=> [ 1, 2, "a", "b", "c", "d"]

static VALUE rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary) { long len = RARRAY_LEN(ary VALUE target_ary; if (argc == 0) { rb_ary_modify_check(ary return ary; } target_ary = ary_ensure_room_for_unshift(ary, argc ary_memcpy0(ary, 0, argc, argv, target_ary ARY_SET_LEN(ary, len + argc return ary; }

values_at(selector, ...) → new_ary Show source

返回一个数组,其中包含与给定选择器相对应的self中的元素。

选择器可以是整数索引或范围。

另请参阅#select。

a = %w{ a b c d e f } a.values_at(1, 3, 5) # => ["b", "d", "f"] a.values_at(1, 3, 5, 7) # => ["b", "d", "f", nil] a.values_at(-1, -2, -2, -7) # => ["f", "e", "e", nil] a.values_at(4..6, 3...6) # => ["e", "f", nil, "d", "e", "f"]

static VALUE rb_ary_values_at(int argc, VALUE *argv, VALUE ary) { return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry }

zip(arg, ...) → new_ary Show source

zip(arg, ...) { |arr| block } → nil

将任何参数转换为数组,然后将self每个参数的相应元素的元素进行合并。

这会生成一系列的ary.size n元素数组,其中n比参数个数多一个。

如果任何参数的大小小于初始数组的大小,nil则会提供值。

如果给出了一个块,则会为每个输出数组调用它,否则返回一个数组数组。

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

static VALUE rb_ary_zip(int argc, VALUE *argv, VALUE ary) { int i, j; long len = RARRAY_LEN(ary VALUE result = Qnil; for (i=0; i<argc; i++) { argv[i] = take_items(argv[i], len } if (rb_block_given_p()) { int arity = rb_block_arity( if (arity > 1) { VALUE work, *tmp; tmp = ALLOCV_N(VALUE, work, argc+1 for (i=0; i<RARRAY_LEN(ary i++) { tmp[0] = RARRAY_AREF(ary, i for (j=0; j<argc; j++) { tmp[j+1] = rb_ary_elt(argv[j], i } rb_yield_values2(argc+1, tmp } if (work) ALLOCV_END(work } else { for (i=0; i<RARRAY_LEN(ary i++) { VALUE tmp = rb_ary_new2(argc+1 rb_ary_push(tmp, RARRAY_AREF(ary, i) for (j=0; j<argc; j++) { rb_ary_push(tmp, rb_ary_elt(argv[j], i) } rb_yield(tmp } } } else { result = rb_ary_new_capa(len for (i=0; i<len; i++) { VALUE tmp = rb_ary_new_capa(argc+1 rb_ary_push(tmp, RARRAY_AREF(ary, i) for (j=0; j<argc; j++) { rb_ary_push(tmp, rb_ary_elt(argv[j], i) } rb_ary_push(result, tmp } } return result; }

ary | other_ary → new_ary Show source

Set Union - 通过与other_ary结合来返回一个新数组,排除任何重复项并保留给定数组的顺序。

它使用hash和eql比较元素?提高效率的方法。

[ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ] [ "c", "d", "a" ] | [ "a", "b", "c" ] #=> [ "c", "d", "a", "b" ]

另见#uniq。

static VALUE rb_ary_or(VALUE ary1, VALUE ary2) { VALUE hash, ary3; long i; ary2 = to_ary(ary2 hash = ary_make_hash(ary1 for (i=0; i<RARRAY_LEN(ary2 i++) { VALUE elt = RARRAY_AREF(ary2, i if (!st_update(RHASH_TBL_RAW(hash), (st_data_t)elt, ary_hash_orset, (st_data_t)elt)) { RB_OBJ_WRITTEN(hash, Qundef, elt } } ary3 = rb_hash_values(hash ary_recycle_hash(hash return ary3; }