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
传递元件,直到块返回nil
或false
,然后停止迭代并返回所有现有元件的阵列。
如果没有给出块,则返回一个枚举器。
另见#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;
}