首页
学习
活动
专区
工具
TVP
发布
精选内容/技术社群/优惠产品,尽在小程序
立即前往

Array

父类:ObjectIncluded 模块:Enumerable

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

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

创建数组

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

代码语言:javascript
复制
ary = [1, "two", 3.0] #=> [1, "two", 3.0]

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

代码语言:javascript
复制
ary = Array.new    #=> []
Array.new(3)       #=> [nil, nil, nil]
Array.new(3, true) #=> [true, true, true]

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

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

代码语言:javascript
复制
Array.new(4) { Hash.new } #=> [{}, {}, {}, {}]

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

代码语言:javascript
复制
empty_table = Array.new(3) { Array.new(3) }
#=> [[nil, nil, nil], [nil, nil, nil], [nil, nil, nil]]

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

代码语言:javascript
复制
Array({:a => "a", :b => "b"}) #=> [[:a, "a"], [:b, "b"]]

使用示例

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

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

访问元素

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

代码语言:javascript
复制
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方法

代码语言:javascript
复制
arr.at(0) #=> 1

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

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

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

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

代码语言:javascript
复制
arr.first #=> 1
arr.last  #=> 6

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

代码语言:javascript
复制
arr.take(3) #=> [1, 2, 3]

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

代码语言:javascript
复制
arr.drop(3) #=> [4, 5, 6]

获取有关数组的信息

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

代码语言:javascript
复制
browsers = ['Chrome', 'Firefox', 'Safari', 'Opera', 'IE']
browsers.length #=> 5
browsers.count #=> 5

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

代码语言:javascript
复制
browsers.empty? #=> false

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

代码语言:javascript
复制
browsers.include?('Konqueror') #=> false

将项目添加到数组

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

代码语言:javascript
复制
arr = [1, 2, 3, 4]
arr.push(5) #=> [1, 2, 3, 4, 5]
arr << 6    #=> [1, 2, 3, 4, 5, 6]

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

代码语言:javascript
复制
arr.unshift(0) #=> [0, 1, 2, 3, 4, 5, 6]

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

代码语言:javascript
复制
arr.insert(3, 'apple')  #=> [0, 1, 2, 'apple', 3, 4, 5, 6]

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

代码语言:javascript
复制
arr.insert(3, 'orange', 'pear', 'grapefruit')
#=> [0, 1, 2, "orange", "pear", "grapefruit", "apple", 3, 4, 5, 6]

从阵列中删除项目

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

代码语言:javascript
复制
arr =  [1, 2, 3, 4, 5, 6]
arr.pop #=> 6
arr #=> [1, 2, 3, 4, 5]

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

代码语言:javascript
复制
arr.shift #=> 1
arr #=> [2, 3, 4, 5]

删除特定索引处的元素:

代码语言:javascript
复制
arr.delete_at(2) #=> 4
arr #=> [2, 3, 5]

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

代码语言:javascript
复制
arr = [1, 2, 2, 3]
arr.delete(2) #=> 2
arr #=> [1,3]

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

代码语言:javascript
复制
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!

代码语言:javascript
复制
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实例中的所有元素将按顺序屈服到所提供的块。

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

代码语言:javascript
复制
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,它将以相反的顺序迭代数组中的元素。

代码语言:javascript
复制
words = %w[first second third fourth fifth sixth]
str = ""
words.reverse_each { |word| str += "#{word} " }
p str #=> "sixth fifth fourth third second first "

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

代码语言:javascript
复制
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]

从数组中选择项目

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

无损选择

代码语言:javascript
复制
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在提供相同的块时具有完全相反的结果:

代码语言:javascript
复制
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]

公共类方法

显示来源

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

代码语言:javascript
复制
Array.[]( 1, 'a', /^A/ ) # => [1, "a", /^A/]
Array[ 1, 'a', /^A/ ]    # => [1, "a", /^A/]
[ 1, 'a', /^A/ ]         # => [1, "a", /^A/]
代码语言:javascript
复制
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生成)。

代码语言:javascript
复制
first_array = ["Matz", "Guido"]

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

first_array.equal? second_array       #=> false

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

代码语言:javascript
复制
Array.new(3){ |index| index ** 2 }
# => [0, 1, 4]

常见的陷阱

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

代码语言:javascript
复制
a = Array.new(2, Hash.new)
# => [{}, {}]

a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {"cat"=>"feline"}]

a[1]['cat'] = 'Felix'
a # => [{"cat"=>"Felix"}, {"cat"=>"Felix"}]

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

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

代码语言:javascript
复制
a = Array.new(2) { Hash.new }
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {}]
代码语言:javascript
复制
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。 此方法可用于检查参数是否为数组。

代码语言:javascript
复制
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
代码语言:javascript
复制
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比较元素?提高效率的方法。

代码语言:javascript
复制
[ 1, 1, 3, 5 ] & [ 3, 2, 1 ]                 #=> [ 1, 3 ]
[ 'a', 'b', 'b', 'z' ] & [ 'a', 'b', 'c' ]   #=> [ 'a', 'b' ]

另见#uniq。

代码语言:javascript
复制
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

代码语言:javascript
复制
[ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
[ 1, 2, 3 ] * ","  #=> "1,2,3"
代码语言:javascript
复制
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

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

代码语言:javascript
复制
[ 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" ]

注意

代码语言:javascript
复制
x += y

等同于

代码语言:javascript
复制
x = x + y

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

另见#concat。

代码语言:javascript
复制
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比较元素?提高效率的方法。

代码语言:javascript
复制
[ 1, 1, 2, 2, 3, 3, 4, 5 ] - [ 1, 2, 4 ]  #=>  [ 3, 3, 5 ]

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

代码语言:javascript
复制
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

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

代码语言:javascript
复制
[ 1, 2 ] << "c" << "d" << [ 3, 4 ]
        #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
代码语言:javascript
复制
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

代码语言:javascript
复制
[ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
[ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1
[ 1, 2 ]             <=> [ 1, :two ]         #=> nil
代码语言:javascript
复制
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中的相应元素,则两个数组相等。

代码语言:javascript
复制
[ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
[ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
[ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false
代码语言:javascript
复制
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

代码语言:javascript
复制
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]               #=> []
代码语言:javascript
复制
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。

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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

代码语言:javascript
复制
require 'abbrev'
%w{ car cone }.abbrev
#=> {"car"=>"car", "ca"=>"car", "cone"=>"cone", "con"=>"cone", "co"=>"cone"}

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

代码语言:javascript
复制
%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

代码语言:javascript
复制
# 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?

代码语言:javascript
复制
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

代码语言:javascript
复制
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
代码语言:javascript
复制
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。 也可以看看 #[]。

代码语言:javascript
复制
a = [ "a", "b", "c", "d", "e" ]
a.at(0)     #=> "a"
a.at(-1)    #=> "e"
代码语言:javascript
复制
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。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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,或始终返回一个数字。它没有定义在每次迭代中实际选取哪个值。

代码语言:javascript
复制
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的文档。

代码语言:javascript
复制
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中删除所有元素。

代码语言:javascript
复制
a = [ "a", "b", "c", "d", "e" ]
a.clear    #=> [ ]
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
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!"]
代码语言:javascript
复制
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的所有组合,然后返回数组本身。

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

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

例子:

代码语言:javascript
复制
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
代码语言:javascript
复制
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的副本。

代码语言:javascript
复制
[ "a", nil, "b", nil, "c", nil ].compact
                  #=> [ "a", "b", "c" ]
代码语言:javascript
复制
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,否则返回数组。

代码语言:javascript
复制
[ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
[ "a", "b", "c" ].compact!           #=> nil
代码语言:javascript
复制
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

代码语言:javascript
复制
[ "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#+。

代码语言:javascript
复制
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的元素的数量。

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

代码语言:javascript
复制
ary = [1, 2, 4, 2]
ary.count                  #=> 4
ary.count(2)               #=> 2
ary.count { |x| x%2 == 0 } #=> 3
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
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.
代码语言:javascript
复制
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 +类型使用

代码语言:javascript
复制
# 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!)

代码语言:javascript
复制
a = [ "a", "b", "b", "b", "c" ]
a.delete("b")                   #=> "b"
a                               #=> ["a", "c"]
a.delete("z")                   #=> nil
a.delete("z") { "not found" }   #=> "not found"
代码语言:javascript
复制
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!

代码语言:javascript
复制
a = ["ant", "bat", "cat", "dog"]
a.delete_at(2)    #=> "cat"
a                 #=> ["ant", "bat", "dog"]
a.delete_at(99)   #=> nil
代码语言:javascript
复制
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!

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

代码语言:javascript
复制
scores = [ 97, 42, 75 ]
scores.delete_if {|score| score < 80 }   #=> [97]
代码语言:javascript
复制
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。

代码语言:javascript
复制
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
代码语言:javascript
复制
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

代码语言:javascript
复制
a = [1, 2, 3, 4, 5, 0]
a.drop(3)             #=> [4, 5, 0]
代码语言:javascript
复制
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

代码语言:javascript
复制
a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]
代码语言:javascript
复制
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,将该元素作为参数传递。返回数组本身。

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

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.each {|x| print x, " -- " }

产生结果:

代码语言:javascript
复制
a -- b -- c --
代码语言:javascript
复制
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相同,但传递元素的索引而不是元素本身。

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

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.each_index {|x| print x, " -- " }

产生结果:

代码语言:javascript
复制
0 -- 1 -- 2 --
代码语言:javascript
复制
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。

代码语言:javascript
复制
[].empty?   #=> true
代码语言:javascript
复制
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。

代码语言:javascript
复制
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数组尾数的负值。

代码语言:javascript
复制
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"
代码语言:javascript
复制
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是最后一个元素。

代码语言:javascript
复制
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]
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.index("b")              #=> 1
a.index("z")              #=> nil
a.index { |x| x == "b" }  #=> 1
代码语言:javascript
复制
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以获得相反的效果。

代码语言:javascript
复制
a = [ "q", "r", "s", "t" ]
a.first     #=> "q"
a.first(2)  #=> ["q", "r"]
代码语言:javascript
复制
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参数确定递归的级别。

代码语言:javascript
复制
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]]
代码语言:javascript
复制
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参数确定递归的级别。

代码语言:javascript
复制
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]]
代码语言:javascript
复制
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。 另请参见对象#冻结?

代码语言:javascript
复制
static VALUE
rb_ary_frozen_p(VALUE ary)
{
    if (OBJ_FROZEN(ary)) return Qtrue;
    return Qfalse;
}

hash → integer Show source

计算这个数组的散列码。

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

另见对象#散列。

代码语言:javascript
复制
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。

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.include?("b")   #=> true
a.include?("z")   #=> false
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.index("b")              #=> 1
a.index("z")              #=> nil
a.index { |x| x == "b" }  #=> 1
代码语言:javascript
复制
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的内容,如有必要,截断或扩展。

代码语言:javascript
复制
a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
a                              #=> ["x", "y", "z"]
代码语言:javascript
复制
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的索引将在数组末尾插入值。

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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

代码语言:javascript
复制
[ "a", "b", "c" ].to_s     #=> "[\"a\", \"b\", \"c\"]"
代码语言:javascript
复制
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

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

代码语言:javascript
复制
[ "a", "b", "c" ].join        #=> "abc"
[ "a", "b", "c" ].join("-")   #=> "a-b-c"
代码语言:javascript
复制
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!

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

代码语言:javascript
复制
a = %w{ a b c d e f }
a.keep_if { |v| v =~ /[aeiou]/ }  #=> ["a", "e"]
代码语言:javascript
复制
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,以获得相反的效果。

代码语言:javascript
复制
a = [ "w", "x", "y", "z" ]
a.last     #=> "z"
a.last(2)  #=> ["y", "z"]
代码语言:javascript
复制
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中的元素数量。 可能为零。

代码语言:javascript
复制
[ 1, 2, 3, 4, 5 ].length   #=> 5
[].length                  #=> 0
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
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!"]
代码语言:javascript
复制
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

代码语言:javascript
复制
a = %w(albatross dog horse)
a.max                                   #=> "horse"
a.max { |a, b| a.length <=> b.length }  #=> "albatross"

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

代码语言:javascript
复制
a = %w[albatross dog horse]
a.max(2)                                  #=> ["horse", "dog"]
a.max(2) {|a, b| a.length <=> b.length }  #=> ["albatross", "horse"]
代码语言:javascript
复制
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

代码语言:javascript
复制
a = %w(albatross dog horse)
a.min                                   #=> "albatross"
a.min { |a, b| a.length <=> b.length }  #=> "dog"

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

代码语言:javascript
复制
a = %w[albatross dog horse]
a.min(2)                                  #=> ["albatross", "dog"]
a.min(2) {|a, b| a.length <=> b.length }  #=> ["dog", "horse"]
代码语言:javascript
复制
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

代码语言:javascript
复制
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

代码语言:javascript
复制
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
代码语言:javascript
复制
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未指定,则产生所有元素的所有排列。

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

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

例子:

代码语言:javascript
复制
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
代码语言:javascript
复制
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获取相反的效果。

代码语言:javascript
复制
a = [ "a", "b", "c", "d" ]
a.pop     #=> "d"
a.pop(2)  #=> ["b", "c"]
a         #=> ["a"]
代码语言:javascript
复制
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

代码语言:javascript
复制
[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([])          #=> []
代码语言:javascript
复制
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,以获得相反的效果。

代码语言:javascript
复制
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]
代码语言:javascript
复制
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。

代码语言:javascript
复制
a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
a.rassoc("two")    #=> [2, "two"]
a.rassoc("four")   #=> nil
代码语言:javascript
复制
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

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

代码语言:javascript
复制
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。

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

代码语言:javascript
复制
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数组中元素长度的所有重复组合,然后返回数组本身。

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

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

例子:

代码语言:javascript
复制
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
代码语言:javascript
复制
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数组元素长度的所有重复排列,然后返回数组本身。

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

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

例子:

代码语言:javascript
复制
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
代码语言:javascript
复制
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的内容,如有必要,截断或扩展。

代码语言:javascript
复制
a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
a                              #=> ["x", "y", "z"]
代码语言:javascript
复制
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元素的新数组。

代码语言:javascript
复制
[ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
[ 1 ].reverse               #=> [1]
代码语言:javascript
复制
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到位。

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.reverse!       #=> ["c", "b", "a"]
a                #=> ["c", "b", "a"]
代码语言:javascript
复制
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以相反的顺序遍历。

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.reverse_each {|x| print x, " " }

produces:

代码语言:javascript
复制
c b a
代码语言:javascript
复制
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。

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

代码语言:javascript
复制
a = [ "a", "b", "b", "b", "c" ]
a.rindex("b")             #=> 3
a.rindex("z")             #=> nil
a.rindex { |x| x == "b" } #=> 3
代码语言:javascript
复制
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是最后一个元素。

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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最后一个元素的数组末尾开始。

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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参数将用作随机数生成器。

代码语言:javascript
复制
a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
a.sample         #=> 7
a.sample(4)      #=> [6, 4, 2, 5]
代码语言:javascript
复制
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值的所有艺术元素。

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

代码语言:javascript
复制
[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。

代码语言:javascript
复制
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

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

代码语言:javascript
复制
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。

代码语言:javascript
复制
# 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以获得相反的效果。

代码语言:javascript
复制
args = [ "-m", "-q", "filename" ]
args.shift     #=> "-m"
args           #=> ["-q", "filename"]

args = [ "-m", "-q", "filename" ]
args.shift(2)  #=> ["-m", "-q"]
args           #=> ["filename"]
代码语言:javascript
复制
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混洗元素的新数组。

代码语言:javascript
复制
a = [ 1, 2, 3 ]           #=> [1, 2, 3]
a.shuffle                 #=> [2, 3, 1]
a                         #=> [1, 2, 3]

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

代码语言:javascript
复制
a.shuffle(random: Random.new(1))  #=> [1, 3, 2]
代码语言:javascript
复制
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在适当位置混合元素。

代码语言:javascript
复制
a = [ 1, 2, 3 ]           #=> [1, 2, 3]
a.shuffle!                #=> [2, 3, 1]
a                         #=> [2, 3, 1]

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

代码语言:javascript
复制
a.shuffle!(random: Random.new(1))  #=> [1, 3, 2]
代码语言:javascript
复制
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

代码语言:javascript
复制
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]               #=> []
代码语言:javascript
复制
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。

代码语言:javascript
复制
a = [ "a", "b", "c" ]
a.slice!(1)     #=> "b"
a               #=> ["a", "c"]
a.slice!(-1)    #=> "c"
a               #=> ["a"]
a.slice!(100)   #=> nil
a               #=> ["a"]
代码语言:javascript
复制
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时,元素的顺序是不可预知的。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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时元素的顺序是不可预知的。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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。

代码语言:javascript
复制
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

代码语言:javascript
复制
[].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

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

代码语言:javascript
复制
mean = ary.sum(0.0) / ary.length

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

代码语言:javascript
复制
["a", "b", "c"].sum("")            #=> "abc"
[[1], [[2]], [3]].sum([])          #=> [1, [2], 3]

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

代码语言:javascript
复制
["a", "b", "c"].join               #=> "abc"
[[1], [[2]], [3]].flatten(1)       #=> [1, [2], 3]

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

代码语言:javascript
复制
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

代码语言:javascript
复制
a = [1, 2, 3, 4, 5, 0]
a.take(3)             #=> [1, 2, 3]
代码语言:javascript
复制
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

代码语言:javascript
复制
a = [1, 2, 3, 4, 5, 0]
a.take_while { |i| i < 3 }  #=> [1, 2]
代码语言:javascript
复制
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对象。

代码语言:javascript
复制
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

代码语言:javascript
复制
static VALUE
rb_ary_to_ary_m(VALUE ary)
{
    return ary;
}

to_h → hash Show source

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

代码语言:javascript
复制
[[:foo, :bar], [1, 2]].to_h
  # => {:foo => :bar, 1 => 2}
代码语言:javascript
复制
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是一个数组数组并转换行和列。

代码语言:javascript
复制
a = [[1,2], [3,4], [5,6]]
a.transpose   #=> [[1, 3, 5], [2, 4, 6]]

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

代码语言:javascript
复制
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 按顺序遍历,并保持第一次出现。

代码语言:javascript
复制
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"]]
代码语言:javascript
复制
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(即没有找到重复项)。

代码语言:javascript
复制
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"]]
代码语言:javascript
复制
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以获得相反的效果。

代码语言:javascript
复制
a = [ "b", "c", "d" ]
a.unshift("a")   #=> ["a", "b", "c", "d"]
a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]
代码语言:javascript
复制
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。

代码语言:javascript
复制
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"]
代码语言:javascript
复制
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则会提供值。

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

代码语言:javascript
复制
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]]
代码语言:javascript
复制
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比较元素?提高效率的方法。

代码语言:javascript
复制
[ "a", "b", "c" ] | [ "c", "d", "a" ]    #=> [ "a", "b", "c", "d" ]
[ "c", "d", "a" ] | [ "a", "b", "c" ]    #=> [ "c", "d", "a", "b" ]

另见#uniq。

代码语言:javascript
复制
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;
}

扫码关注腾讯云开发者

领取腾讯云代金券

http://www.vxiaotou.com