类 Array

Array 对象是对象的有序、整数索引集合,称为元素;该对象表示数组数据结构

一个元素可以是任何对象(甚至另一个数组);元素可以是任何不同类型对象的混合。

使用数组的重要数据结构包括

还有类似数组的数据结构

数组索引

与 C 或 Java 中一样,数组索引从 0 开始。

非负索引是从第一个元素的偏移量

  • 索引 0 表示第一个元素。

  • 索引 1 表示第二个元素。

  • ……

负索引是从数组末尾向后的偏移量

  • 索引 -1 表示最后一个元素。

  • 索引 -2 表示倒数第二个元素。

  • ……

范围内和范围外索引

当且仅当非负索引小于数组大小时,它才在范围内。对于一个包含 3 个元素的数组

  • 索引 0 到 2 在范围内。

  • 索引 3 超出范围。

当且仅当负索引的绝对值不大于数组大小时,它才在范围内。对于一个包含 3 个元素的数组

  • 索引 -1 到 -3 在范围内。

  • 索引 -4 超出范围。

有效索引

尽管数组的有效索引始终是一个整数,但某些方法(无论是在 Array 类内部还是在其他地方)接受一个或多个非整数参数,这些参数是可转换为整数的对象

创建数组

你可以使用以下方式显式创建 Array 对象

  • 数组字面量

    [1, 'one', :one, [2, 'two', :two]]
    
  • %w 或 %W 字符串数组字面量

    %w[foo bar baz] # => ["foo", "bar", "baz"]
    %w[1 % *]       # => ["1", "%", "*"]
    
  • %i 或 %I 符号数组字面量

    %i[foo bar baz] # => [:foo, :bar, :baz]
    %i[1 % *]       # => [:"1", :%, :*]
    
  • 方法 Kernel#Array

    Array(["a", "b"])             # => ["a", "b"]
    Array(1..5)                   # => [1, 2, 3, 4, 5]
    Array(key: :value)            # => [[:key, :value]]
    Array(nil)                    # => []
    Array(1)                      # => [1]
    Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
    
  • 方法 Array.new

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

    请注意,上面的最后一个示例使用对同一对象的引用填充数组。仅当该对象是原生不可变的对象(如符号、数字、niltruefalse)时,才建议这样做。

    另一种使用块创建包含各种对象的数组的方法;此用法对于可变对象(如哈希、字符串或其他数组)是安全的

    Array.new(4) {|i| i.to_s } # => ["0", "1", "2", "3"]
    

    以下是创建多维数组的方法

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

许多 Ruby 方法(无论是在核心库还是在标准库中)都提供了实例方法 to_a,用于将对象转换为数组。

示例用法

除了通过 Enumerable 模块混合的方法之外,Array 类还具有访问、搜索和以其他方式操作数组的专有方法。

下面说明了一些更常见的方法。

访问元素

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

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

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

arr.at(0) #=> 1

slice 方法的工作方式与 Array#[] 完全相同。

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

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

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

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

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

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

drop 的作用与 take 相反,它通过返回删除 n 个元素后的元素来实现

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

获取有关 Array 的信息

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

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

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

browsers.empty? #=> false

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

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

向数组添加项

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

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

unshift 会将新项添加到数组的开头。

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

使用 insert,你可以将新元素添加到数组中的任何位置。

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

使用 insert 方法,你也可以一次插入多个值

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

Array 中删除项

方法 pop 会删除数组中的最后一个元素并将其返回

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

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

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

要删除特定索引处的元素

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

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

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

如果你需要从数组中删除 nil 值,则一个有用的方法是 compact

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

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

它具有非破坏性方法 uniq 和破坏性方法 uniq!

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

遍历数组

与所有包含 Enumerable 模块的类一样,Array 具有 each 方法,该方法定义应遍历哪些元素以及如何遍历。对于 Array 的 eachArray 实例中的所有元素都会按顺序传递给提供的块。

请注意,此操作不会更改数组。

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

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

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

map 方法可用于创建基于原始数组的新数组,但其值已由提供的块修改

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

Array 中选择项

可以根据代码块中定义的条件从数组中选择元素。选择操作可以是破坏性的,也可以是非破坏性的。破坏性操作会修改调用它们的数组,而非破坏性方法通常会返回一个包含所选元素的新数组,但会保持原始数组不变。

非破坏性选择

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! 分别是 selectreject 对应的破坏性方法。

类似于 selectreject 的关系,delete_ifkeep_if 在使用相同的代码块时会产生完全相反的结果。

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

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

本页内容

首先,介绍一下其他地方的内容。Array

在这里,Array 类提供了以下方面有用的方法:

创建 Array 的方法

  • ::[]:返回一个用给定对象填充的新数组。

  • ::new:返回一个新数组。

  • ::try_convert:返回一个从给定对象创建的新数组。

另请参阅 创建数组

查询方法

  • all?:返回是否所有元素都满足给定条件。

  • any?:返回是否任何元素满足给定条件。

  • count:返回满足给定条件的元素的计数。

  • empty?:返回是否存在任何元素。

  • find_index(别名为 index):返回满足给定条件的第一个元素的索引。

  • hash:返回整数哈希码。

  • include?:返回是否存在任何元素 == 给定对象。

  • length(别名为 size):返回元素的计数。

  • none?:返回是否没有元素 == 给定对象。

  • one?:返回是否正好有一个元素 == 给定对象。

  • rindex:返回满足给定条件的最后一个元素的索引。

比较方法

  • #<=>: 返回 -1、0 或 1,分别表示 self 小于、等于或大于给定对象。

  • ==:返回是否 self 中的每个元素 == 给定对象中的对应元素。

  • eql?:返回是否 self 中的每个元素 eql? 给定对象中的对应元素。

获取方法

这些方法不会修改 self

  • [](别名为 slice):返回由给定参数确定的连续元素。

  • assoc:返回第一个元素是数组且其第一个元素 == 给定对象的元素。

  • at:返回给定偏移量的元素。

  • bsearch:返回通过给定代码块确定的二分搜索选择的元素。

  • bsearch_index:返回通过给定代码块确定的二分搜索选择的元素的索引。

  • compact:返回包含所有非 nil 元素的数组。

  • dig:返回由给定索引和其他参数指定的嵌套对象中的对象。

  • drop:返回由给定索引确定的尾部元素。

  • drop_while:返回由给定代码块确定的尾部元素。

  • fetch:返回给定偏移量的元素。

  • fetch_values:返回给定偏移量的元素。

  • first:返回一个或多个前导元素。

  • last:返回一个或多个尾部元素。

  • max:返回一个或多个最大值元素,由 #<=> 或给定代码块确定。

  • min:返回一个或多个最小值元素,由 #<=> 或给定代码块确定。

  • minmax:返回最小值和最大值元素,由 #<=> 或给定代码块确定。

  • rassoc:返回第一个元素是数组且其第二个元素 == 给定对象的元素。

  • reject:返回一个包含未被给定代码块拒绝的元素的数组。

  • reverse:返回所有元素的反向顺序。

  • rotate:返回所有元素,其中一些元素从一端旋转到另一端。

  • sample:返回一个或多个随机元素。

  • select(别名为 filter):返回一个包含由给定代码块选择的元素的数组。

  • shuffle:返回随机顺序的元素。

  • sort:返回由 #<=> 或给定代码块确定的顺序的所有元素。

  • take:返回由给定索引确定的前导元素。

  • take_while:返回由给定代码块确定的前导元素。

  • uniq:返回包含非重复元素的数组。

  • values_at:返回给定偏移量的元素。

赋值方法

这些方法会添加、替换或重新排序 self 中的元素。

  • <<:追加一个元素。

  • []=:用给定对象赋值指定的元素。

  • concat:追加给定数组中的所有元素。

  • fill:用指定的对象替换指定的元素。

  • flatten!:用该数组中的元素替换 self 中的每个嵌套数组。

  • initialize_copy(别名为 replace):用给定数组的内容替换 self 的内容。

  • insert:在给定偏移量处插入给定对象;不替换元素。

  • push(别名为 append):追加元素。

  • reverse!:用其反向元素替换 self

  • rotate!:用其旋转元素替换 self

  • shuffle!:用其随机顺序的元素替换 self

  • sort!:用其排序后的元素替换 self,由 #<=> 或给定代码块确定。

  • sort_by!:用其排序后的元素替换 self,由给定代码块确定。

  • unshift(别名为 prepend):在开头添加元素。

删除方法

这些方法都会从 self 中移除元素

  • clear:移除所有元素。

  • compact!:移除所有 nil 元素。

  • delete:移除等于给定对象的元素。

  • delete_at:移除给定偏移量的元素。

  • delete_if:移除由给定代码块指定的元素。

  • keep_if:移除不由给定代码块指定的元素。

  • pop:移除并返回最后一个元素。

  • reject!:移除由给定代码块指定的元素。

  • select!(别名为 filter!):移除不由给定代码块指定的元素。

  • shift:移除并返回第一个元素。

  • slice!:移除并返回一系列元素。

  • uniq!:移除重复项。

组合方法

  • #&:返回一个包含在 self 和给定数组中都存在的元素的数组。

  • +:返回一个包含 self 的所有元素,后跟给定数组的所有元素的数组。

  • -:返回一个包含 self 中所有但不在给定数组中找到的元素的数组。

  • #|:返回一个包含 self 的所有元素和给定数组的所有元素的数组,并删除重复项。

  • difference:返回一个包含 self 中所有但不在任何给定数组中找到的元素的数组。

  • intersection:返回一个包含 self 和每个给定数组中都存在的元素的数组。

  • product:返回或产生 self 和给定数组中元素的所有组合。

  • reverse:返回一个包含 self 中所有元素的反向顺序的数组。

  • union:返回一个包含 self 的所有元素和给定数组的所有元素的数组,并删除重复项。

迭代方法

  • combination:使用 self 中元素的组合调用给定的块;组合不会多次使用同一个元素。

  • cycle:使用每个元素调用给定的块,然后重复操作,执行指定的次数或无限次。

  • each:将每个元素传递给给定的块。

  • each_index:将每个元素的索引传递给给定的块。

  • permutation:使用 self 中元素的排列调用给定的块;排列不会多次使用同一个元素。

  • repeated_combination:使用 self 中元素的组合调用给定的块;组合可以多次使用同一个元素。

  • repeated_permutation:使用 self 中元素的排列调用给定的块;排列可以多次使用同一个元素。

  • reverse_each:以相反的顺序将每个元素传递给给定的块。

转换方法

  • collect (别名为 map):返回一个包含每个元素的块返回值的数组。

  • collect! (别名为 map!):用块返回值替换每个元素。

  • flatten:返回一个数组,它是 self 的递归扁平化版本。

  • inspect (别名为 to_s):返回一个包含元素的新的 String

  • join:返回一个新的 String,其中包含由字段分隔符连接的元素。

  • to_a:返回 self 或一个包含所有元素的新数组。

  • to_ary:返回 self

  • to_h:返回由元素组成的新哈希表。

  • transpose:转置 self,它必须是一个数组的数组。

  • zip:返回一个新的数组的数组,其中包含 self 和给定的数组。

其他方法

  • *:返回以下其中一项

    • 使用整数参数 n,返回一个新的数组,它是 selfn 个副本的连接。

    • 使用字符串参数 field_separator,返回一个新的字符串,它等价于 join(field_separator)

  • pack:将元素打包为二进制序列。

  • sum:根据 + 或给定的块返回元素的总和。

公共类方法

[](*args) 点击切换源代码

返回一个新数组,其中填充了给定的对象

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

相关:请参阅 创建数组的方法

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

    return ary;
}
new → new_empty_array 点击切换源代码
new(array) → new_array
new(size, default_value = nil) → new_array
new(size = 0) {|index| ... } → new_array

返回一个新数组。

如果没有块且没有给出参数,则返回一个新的空数组

Array.new # => []

如果没有块且给出了数组参数,则返回一个具有相同元素的新数组

Array.new([:foo, 'bar', 2]) # => [:foo, "bar", 2]

如果没有块且给出了整数参数,则返回一个包含给定 default_value 的多个实例的新数组

Array.new(0)    # => []
Array.new(3)    # => [nil, nil, nil]
Array.new(2, 3) # => [3, 3]

如果给出了块,则返回一个具有给定 size 的数组;使用范围 (0...size) 中的每个 index 调用该块;返回的数组中该 index 处的元素是块的返回值

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

对于 Ruby 新手来说,一个常见的陷阱是将表达式作为 default_value 提供

array = Array.new(2, {})
array # => [{}, {}]
array[0][:a] = 1
array # => [{a: 1}, {a: 1}], as array[0] and array[1] are same object

如果你希望数组的元素是不同的,则应传递一个块

array = Array.new(2) { {} }
array # => [{}, {}]
array[0][:a] = 1
array # => [{a: 1}, {}], as array[0] and array[1] are different objects

如果第一个参数不是数组或整数可转换对象,则引发 TypeError。如果第一个参数是负整数,则引发 ArgumentError

相关:请参阅 创建数组的方法

static VALUE
rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
{
    long len;
    VALUE size, val;

    rb_ary_modify(ary);
    if (argc == 0) {
        rb_ary_reset(ary);
        RUBY_ASSERT(ARY_EMBED_P(ary));
        RUBY_ASSERT(ARY_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(object) → object, new_array, or nil 点击切换源代码

尝试基于给定的 object 返回一个数组。

如果 object 是一个数组,则返回 object

否则,如果 object 响应 :to_ary,则调用 object.to_ary:如果返回值是一个数组或 nil,则返回该值;否则,引发 TypeError

否则返回 nil

相关:请参阅 创建数组的方法

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

公共实例方法

self & other_array → new_array 点击切换源代码

返回一个新数组,其中包含 selfother_array交集;也就是说,包含在 selfother_array 中都找到的那些元素

[0, 1, 2, 3] & [1, 2] # => [1, 2]

省略重复项

[0, 1, 1, 0] & [0, 1] # => [0, 1]

保留 self 中的顺序

[0, 1, 2] & [3, 2, 1, 0] # => [0, 1, 2]

使用方法 #eql?(在 self 的每个元素中定义)识别公共元素。

相关:请参阅 组合方法

static VALUE
rb_ary_and(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3, v;
    st_data_t vv;
    long i;

    ary2 = to_ary(ary2);
    ary3 = rb_ary_new();
    if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return ary3;

    if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
        for (i=0; i<RARRAY_LEN(ary1); i++) {
            v = RARRAY_AREF(ary1, i);
            if (!rb_ary_includes_by_eql(ary2, v)) continue;
            if (rb_ary_includes_by_eql(ary3, v)) continue;
            rb_ary_push(ary3, v);
        }
        return ary3;
    }

    hash = ary_make_hash(ary2);

    for (i=0; i<RARRAY_LEN(ary1); i++) {
        v = RARRAY_AREF(ary1, i);
        vv = (st_data_t)v;
        if (rb_hash_stlike_delete(hash, &vv, 0)) {
            rb_ary_push(ary3, v);
        }
    }

    return ary3;
}
self * n → new_array 点击切换源代码
self * string_separator → new_string

当给定非负整数参数 n 时,返回通过连接 selfn 个副本构建的新数组

a = ['x', 'y']
a * 3 # => ["x", "y", "x", "y", "x", "y"]

当给定字符串参数 string_separator 时,等效于 self.join(string_separator)

[0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
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_cArray, 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_cArray, 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:
    return ary2;
}
self + other_array → new_array 点击切换源代码

返回一个新数组,其中包含 self 的所有元素,后跟 other_array 的所有元素

a = [0, 1] + [2, 3]
a # => [0, 1, 2, 3]

相关:请参阅 组合方法

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;
}
self - other_array → new_array 点击切换源代码

返回一个仅包含 self 中未在 other_array 中找到的元素的新数组;保留 self 中的顺序

[0, 1, 1, 2, 1, 1, 3, 1, 1] - [1]             # => [0, 2, 3]
[0, 1, 1, 2, 1, 1, 3, 1, 1] - [3, 2, 0, :foo] # => [1, 1, 1, 1, 1, 1]
[0, 1, 2] - [:foo]                            # => [0, 1, 2]

使用方法 #eql?(在 self 的每个元素中定义)比较元素。

相关:请参阅 组合方法

VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
    VALUE ary3;
    VALUE hash;
    long i;

    ary2 = to_ary(ary2);
    if (RARRAY_LEN(ary2) == 0) { return ary_make_shared_copy(ary1); }
    ary3 = rb_ary_new();

    if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN || RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
        for (i=0; i<RARRAY_LEN(ary1); i++) {
            VALUE elt = rb_ary_elt(ary1, i);
            if (rb_ary_includes_by_eql(ary2, elt)) continue;
            rb_ary_push(ary3, elt);
        }
        return ary3;
    }

    hash = ary_make_hash(ary2);
    for (i=0; i<RARRAY_LEN(ary1); i++) {
        if (rb_hash_stlike_lookup(hash, RARRAY_AREF(ary1, i), NULL)) continue;
        rb_ary_push(ary3, rb_ary_elt(ary1, i));
    }

    return ary3;
}
self << object → self 点击切换源代码

object 追加为 self 的最后一个元素;返回 self

[:foo, 'bar', 2] << :baz # => [:foo, "bar", 2, :baz]

object 作为单个元素追加,即使它是另一个数组

[:foo, 'bar', 2] << [3, 4] # => [:foo, "bar", 2, [3, 4]]

相关:请参阅 赋值方法

VALUE
rb_ary_push(VALUE ary, VALUE item)
{
    long idx = RARRAY_LEN((ary_verify(ary), 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);
    ary_verify(ary);
    return ary;
}
self <=> other_array → -1, 0, or 1 点击切换源代码

如果确定 self 小于、等于或大于 other_array,则返回 -1、0 或 1。

(0...self.size) 中迭代每个索引 i

  • result[i] 计算为 self[i] <=> other_array[i]

  • 如果 result[i] 为 1,则立即返回 1

    [0, 1, 2] <=> [0, 0, 2] # => 1
    
  • 如果 result[i] 为 -1,则立即返回 -1

    [0, 1, 2] <=> [0, 2, 2] # => -1
    
  • 如果 result[i] 为 0,则继续。

当每个 result 为 0 时,返回 self.size <=> other_array.size(请参阅 Integer#<=>)

[0, 1, 2] <=> [0, 1]        # => 1
[0, 1, 2] <=> [0, 1, 2]     # => 0
[0, 1, 2] <=> [0, 1, 2, 3]  # => -1

请注意,当 other_array 大于 self 时,其尾随元素不会影响结果

[0, 1, 2] <=> [0, 1, 2, -3] # => -1
[0, 1, 2] <=> [0, 1, 2, 0]  # => -1
[0, 1, 2] <=> [0, 1, 2, 3]  # => -1

相关:请参阅 比较方法

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 (!UNDEF_P(v)) return v;
    len = RARRAY_LEN(ary1) - RARRAY_LEN(ary2);
    if (len == 0) return INT2FIX(0);
    if (len > 0) return INT2FIX(1);
    return INT2FIX(-1);
}
self == other_array → true or false 点击切换源代码

返回是否同时满足以下条件

  • selfother_array 的大小相同。

  • 它们的相应元素相同;也就是说,对于 (0...self.size) 中的每个索引 iself[i] == other_array[i]

示例

[:foo, 'bar', 2] == [:foo, 'bar', 2]   # => true
[:foo, 'bar', 2] == [:foo, 'bar', 2.0] # => true
[:foo, 'bar', 2] == [:foo, 'bar']      # => false # Different sizes.
[:foo, 'bar', 2] == [:foo, 'bar', 3]   # => false # Different elements.

此方法与方法 Array#eql? 不同,后者使用 Object#eql? 比较元素。

相关:请参阅 比较方法

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);
}
self[index] → object or nil 点击切换源代码
self[start, length] → object or nil
self[range] → object or nil
self[aseq] → object or nil

self 返回元素;不修改 self

简而言之

a = [:foo, 'bar', 2]

# Single argument index: returns one element.
a[0]     # => :foo          # Zero-based index.
a[-1]    # => 2             # Negative index counts backwards from end.

# Arguments start and length: returns an array.
a[1, 2]  # => ["bar", 2]
a[-2, 2] # => ["bar", 2]    # Negative start counts backwards from end.

# Single argument range: returns an array.
a[0..1]  # => [:foo, "bar"]
a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
a[-2..2] # => ["bar", 2]    # Negative range-end counts backwards from end.

当给定单个整数参数 index 时,返回偏移量 index 处的元素

a = [:foo, 'bar', 2]
a[0] # => :foo
a[2] # => 2
a # => [:foo, "bar", 2]

如果 index 为负,则从 self 的末尾向后计数

a = [:foo, 'bar', 2]
a[-1] # => 2
a[-2] # => "bar"

如果 index 超出范围,则返回 nil

当给定两个 Integer 参数 startlength 时,返回一个大小为 length 的新 Array,其中包含从偏移量 start 开始的连续元素

a = [:foo, 'bar', 2]
a[0, 2] # => [:foo, "bar"]
a[1, 2] # => ["bar", 2]

如果 start + length 大于 self.length,则返回从偏移量 start 到末尾的所有元素

a = [:foo, 'bar', 2]
a[0, 4] # => [:foo, "bar", 2]
a[1, 3] # => ["bar", 2]
a[2, 2] # => [2]

如果 start == self.sizelength >= 0,则返回一个新的空 Array

如果 length 为负数,则返回 nil

当给定单个 Range 参数 range 时,将 range.min 视为上面的 start,将 range.size 视为上面的 length

a = [:foo, 'bar', 2]
a[0..1] # => [:foo, "bar"]
a[1..2] # => ["bar", 2]

特殊情况:如果 range.start == a.size,则返回一个新的空 Array

如果 range.end 为负,则从末尾计算结束索引

a = [:foo, 'bar', 2]
a[0..-1] # => [:foo, "bar", 2]
a[0..-2] # => [:foo, "bar"]
a[0..-3] # => [:foo]

如果 range.start 为负,则从末尾计算起始索引

a = [:foo, 'bar', 2]
a[-1..2] # => [2]
a[-2..2] # => ["bar", 2]
a[-3..2] # => [:foo, "bar", 2]

如果 range.start 大于数组大小,则返回 nil

a = [:foo, 'bar', 2]
a[4..1] # => nil
a[4..0] # => nil
a[4..-1] # => nil

当给定单个 Enumerator::ArithmeticSequence 参数 aseq 时,返回一个与序列生成的索引相对应的元素 Array

a = ['--', 'data1', '--', 'data2', '--', 'data3']
a[(1..).step(2)] # => ["data1", "data2", "data3"]

与使用范围切片不同,如果算术序列的开头或结尾大于数组大小,则抛出 RangeError

a = ['--', 'data1', '--', 'data2', '--', 'data3']
a[(1..11).step(2)]
# RangeError (((1..11).step(2)) out of range)
a[(7..).step(2)]
# RangeError (((7..).step(2)) out of range)

如果给定的参数是单个参数,并且其类型不是列出的类型之一,则尝试将其转换为 Integer,如果无法转换,则引发错误

a = [:foo, 'bar', 2]
# Raises TypeError (no implicit conversion of Symbol into Integer):
a[:foo]

相关:请参阅 获取方法

VALUE
rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
    rb_check_arity(argc, 1, 2);
    if (argc == 2) {
        return rb_ary_aref2(ary, argv[0], argv[1]);
    }
    return rb_ary_aref1(ary, argv[0]);
}
也别名为:slice
self[index] = object → object 点击切换源代码
self[start, length] = object → object
self[range] = object → object

根据给定的 objectself 中分配元素;返回 object

简而言之

a_orig = [:foo, 'bar', 2]

# With argument index.
a = a_orig.dup
a[0] = 'foo' # => "foo"
a # => ["foo", "bar", 2]
a = a_orig.dup
a[7] = 'foo' # => "foo"
a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]

# With arguments start and length.
a = a_orig.dup
a[0, 2] = 'foo' # => "foo"
a # => ["foo", 2]
a = a_orig.dup
a[6, 50] = 'foo' # => "foo"
a # => [:foo, "bar", 2, nil, nil, nil, "foo"]

# With argument range.
a = a_orig.dup
a[0..1] = 'foo' # => "foo"
a # => ["foo", 2]
a = a_orig.dup
a[6..50] = 'foo' # => "foo"
a # => [:foo, "bar", 2, nil, nil, nil, "foo"]

当给定 Integer 参数 index 时,将 object 分配给 self 中的元素。

如果 index 为非负数,则将 object 分配给偏移量 index 处的元素

a = [:foo, 'bar', 2]
a[0] = 'foo' # => "foo"
a # => ["foo", "bar", 2]

如果 index 大于 self.length,则扩展数组

a = [:foo, 'bar', 2]
a[7] = 'foo' # => "foo"
a # => [:foo, "bar", 2, nil, nil, nil, nil, "foo"]

如果 index 为负数,则从数组末尾向后计数

a = [:foo, 'bar', 2]
a[-1] = 'two' # => "two"
a # => [:foo, "bar", "two"]

当给定 Integer 参数 startlengthobject 不是 Array 时,删除从偏移量 start 开始的 length - 1 个元素,并在偏移量 start 处分配 object

a = [:foo, 'bar', 2]
a[0, 2] = 'foo' # => "foo"
a # => ["foo", 2]

如果 start 为负数,则从数组末尾向后计数

a = [:foo, 'bar', 2]
a[-2, 2] = 'foo' # => "foo"
a # => [:foo, "foo"]

如果 start 为非负数并且在数组外部 (>= self.size),则使用 nil 扩展数组,在偏移量 start 处分配 object,并忽略 length

a = [:foo, 'bar', 2]
a[6, 50] = 'foo' # => "foo"
a # => [:foo, "bar", 2, nil, nil, nil, "foo"]

如果 length 为零,则移动偏移量 start 和后面的元素,并在偏移量 start 处分配 object

a = [:foo, 'bar', 2]
a[1, 0] = 'foo' # => "foo"
a # => [:foo, "foo", "bar", 2]

如果 length 对于现有数组来说太大,则不扩展数组

a = [:foo, 'bar', 2]
a[1, 5] = 'foo' # => "foo"
a # => [:foo, "foo"]

当给定 Range 参数 rangeobject 不是 Array 时,从偏移量 start 处开始移除 length - 1 个元素,并在偏移量 start 处分配 object

a = [:foo, 'bar', 2]
a[0..1] = 'foo' # => "foo"
a # => ["foo", 2]

如果 range.begin 为负数,则从数组末尾向后计数。

a = [:foo, 'bar', 2]
a[-2..2] = 'foo' # => "foo"
a # => [:foo, "foo"]

如果数组长度小于 range.begin,则用 nil 扩展数组,在偏移量 range.begin 处分配 object,并忽略 length

a = [:foo, 'bar', 2]
a[6..50] = 'foo' # => "foo"
a # => [:foo, "bar", 2, nil, nil, nil, "foo"]

如果 range.end 为零,则移动偏移量 start 及其之后的元素,并在偏移量 start 处分配 object

a = [:foo, 'bar', 2]
a[1..0] = 'foo' # => "foo"
a # => [:foo, "foo", "bar", 2]

如果 range.end 为负数,则在偏移量 start 处分配 object,保留其后的 range.end.abs -1 个元素,并删除超出此范围的元素。

a = [:foo, 'bar', 2]
a[1..-1] = 'foo' # => "foo"
a # => [:foo, "foo"]
a = [:foo, 'bar', 2]
a[1..-2] = 'foo' # => "foo"
a # => [:foo, "foo", 2]
a = [:foo, 'bar', 2]
a[1..-3] = 'foo' # => "foo"
a # => [:foo, "foo", "bar", 2]
a = [:foo, 'bar', 2]

如果 range.end 对于现有数组来说太大,则替换数组元素,但不会用 nil 值扩展数组。

a = [:foo, 'bar', 2]
a[1..5] = 'foo' # => "foo"
a # => [:foo, "foo"]

相关:请参阅 赋值方法

static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
    long offset, beg, len;

    rb_check_arity(argc, 2, 3);
    rb_ary_modify_check(ary);
    if (argc == 3) {
        beg = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        return ary_aset_by_rb_ary_splice(ary, beg, len, argv[2]);
    }
    if (FIXNUM_P(argv[0])) {
        offset = FIX2LONG(argv[0]);
        return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
    }
    if (rb_range_beg_len(argv[0], &beg, &len, RARRAY_LEN(ary), 1)) {
        /* check if idx is Range */
        return ary_aset_by_rb_ary_splice(ary, beg, len, argv[1]);
    }

    offset = NUM2LONG(argv[0]);
    return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
}
all? → true 或 false 点击以切换源代码
all?(object) → true 或 false
all? {|element| ... } → true 或 false

返回 self 的每个元素是否都满足给定条件。

如果没有代码块且没有参数,则返回 self 的每个元素是否都是真值。

[[], {}, '', 0, 0.0, Object.new].all? # => true  # All truthy objects.
[[], {}, '', 0, 0.0, nil].all?        # => false # nil is not truthy.
[[], {}, '', 0, 0.0, false].all?      # => false # false is not truthy.

如果给定参数 object,则返回 self 中的每个元素 ele 是否满足 object === ele

[0, 0, 0].all?(0)                    # => true
[0, 1, 2].all?(1)                    # => false
['food', 'fool', 'foot'].all?(/foo/) # => true
['food', 'drink'].all?(/foo/)        # => false

如果给定代码块,则对 self 中的每个元素调用该代码块;返回该代码块是否只返回真值。

[0, 1, 2].all? { |ele| ele < 3 } # => true
[0, 1, 2].all? { |ele| ele < 2 } # => false

如果同时给定代码块和参数 object,则忽略该代码块,并按上述方式使用 object

特殊情况:如果 self 为空,则返回 true(无论给定任何参数或代码块)。

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);

    rb_check_arity(argc, 0, 1);
    if (!len) return Qtrue;
    if (argc) {
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (!RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
        }
    }
    else if (!rb_block_given_p()) {
        for (i = 0; i < len; ++i) {
            if (!RTEST(RARRAY_AREF(ary, i))) return Qfalse;
        }
    }
    else {
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (!RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
        }
    }
    return Qtrue;
}
any? → true 或 false 点击以切换源代码
any?(object) → true 或 false
any? {|element| ... } → true 或 false

返回 self 的任何元素是否满足给定条件。

如果没有代码块且没有参数,则返回 self 的任何元素是否为真值。

[nil, false, []].any? # => true  # Array object is truthy.
[nil, false, {}].any? # => true  # Hash object is truthy.
[nil, false, ''].any? # => true  # String object is truthy.
[nil, false].any?     # => false # Nil and false are not truthy.

如果给定参数 object,则返回 self 中的任何元素 ele 是否满足 object === ele

[nil, false, 0].any?(0)          # => true
[nil, false, 1].any?(0)          # => false
[nil, false, 'food'].any?(/foo/) # => true
[nil, false, 'food'].any?(/bar/) # => false

如果给定代码块,则对 self 中的每个元素调用该代码块;返回该代码块是否返回任何真值。

[0, 1, 2].any? {|ele| ele < 1 } # => true
[0, 1, 2].any? {|ele| ele < 0 } # => false

如果同时给定代码块和参数 object,则忽略该代码块,并按上述方式使用 object

特殊情况:如果 self 为空,则返回 false(无论给定任何参数或代码块)。

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);

    rb_check_arity(argc, 0, 1);
    if (!len) return Qfalse;
    if (argc) {
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qtrue;
        }
    }
    else if (!rb_block_given_p()) {
        for (i = 0; i < len; ++i) {
            if (RTEST(RARRAY_AREF(ary, i))) return Qtrue;
        }
    }
    else {
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qtrue;
        }
    }
    return Qfalse;
}
append(*objects) → self

objects 中的每个参数追加到 self;返回 self

a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
a.push(:baz, :bat)   # => [:foo, "bar", 2, :baz, :bat]

即使参数是另一个数组,也会将每个参数作为单个元素追加。

a = [:foo, 'bar', 2]               # => [:foo, "bar", 2]
a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]

相关:请参阅 赋值方法

别名: push
assoc(object) → found_array 或 nil 点击以切换源代码

返回 self 中第一个 ele,使得 ele 是一个数组且 ele[0] == object

a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
a.assoc(4) # => [4, 5, 6]

如果未找到此类元素,则返回 nil

相关信息: Array#rassoc;另请参阅 用于提取的方法

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) → object 或 nil 点击以切换源代码

返回由给定 index 指定的 self 的元素;如果不存在此类元素,则返回 nilindex 必须是 可转换为整数的对象

对于非负数 index,返回偏移量 index 处的 self 的元素。

a = [:foo, 'bar', 2]
a.at(0)   # => :foo
a.at(2)   # => 2
a.at(2.0) # => 2

对于负数 index,则从 self 的末尾向后计数。

a.at(-2) # => "bar"

相关信息: Array#[];另请参阅 用于提取的方法

VALUE
rb_ary_at(VALUE ary, VALUE pos)
{
    return rb_ary_entry(ary, NUM2LONG(pos));
}
bsearch {|element| ... } → found_element 或 nil 点击以切换源代码
bsearch → new_enumerator

返回通过二分查找从 self 中找到的元素,如果搜索没有找到合适的元素,则返回 nil

请参阅 二分查找

相关:请参阅 获取方法

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 {|element| ... } → integer 或 nil 点击以切换源代码
bsearch_index → new_enumerator

返回通过二分查找从 self 中找到的元素的整数索引,如果搜索没有找到合适的元素,则返回 nil

请参阅 二分查找

相关:请参阅 获取方法

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 (!RTEST(v)) {
            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 = 0; break;
              case -1: smaller = 1;
            }
        }
        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 → self 点击以切换源代码

self 中删除所有元素;返回 self

a = [:foo, 'bar', 2]
a.clear # => []

相关信息:请参阅 用于删除的方法

VALUE
rb_ary_clear(VALUE ary)
{
    rb_ary_modify_check(ary);
    if (ARY_SHARED_P(ary)) {
        rb_ary_unshare(ary);
        FL_SET_EMBED(ary);
        ARY_SET_EMBED_LEN(ary, 0);
    }
    else {
        ARY_SET_LEN(ary, 0);
        if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
            ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
        }
    }
    ary_verify(ary);
    return ary;
}
collect {|element| ... } → new_array 点击以切换源代码
collect → new_enumerator

如果给定代码块,则对 self 的每个元素调用该代码块;返回一个新数组,其元素是来自代码块的返回值。

a = [:foo, 'bar', 2]
a1 = a.map {|element| element.class }
a1 # => [Symbol, String, Integer]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息: collect!;另请参阅 用于转换的方法

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
collect! {|element| ... } → new_array 点击以切换源代码
collect! → new_enumerator

如果给定代码块,则对 self 的每个元素调用该代码块,并将该元素替换为代码块的返回值;返回 self

a = [:foo, 'bar', 2]
a.map! { |element| element.class } # => [Symbol, String, Integer]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息: collect;另请参阅 用于转换的方法

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;
}
也别名为: map!
combination(count) {|element| ... } → self 点击以切换源代码
combination(count) → new_enumerator

当给定一个代码块和一个正 可转换为整数的对象 参数 count (0 < count <= self.size) 时,将调用代码块,参数为大小为 countself 的每个组合;返回 self

a = %w[a b c]                                   # => ["a", "b", "c"]
a.combination(2) {|combination| p combination } # => ["a", "b", "c"]

输出

["a", "b"]
["a", "c"]
["b", "c"]

不保证生成的组合的顺序。

count 为零时,将用新的空数组调用代码块一次。

a.combination(0) {|combination| p combination }
[].combination(0) {|combination| p combination }

输出

[]
[]

count 为负数或大于 self.sizeself 为非空时,不会调用代码块。

a.combination(-1) {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]
a.combination(4)  {|combination| fail 'Cannot happen' } # => ["a", "b", "c"]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息: Array#permutation;另请参阅 用于迭代的方法

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_array 点击以切换源代码

返回一个新数组,该数组仅包含来自 self 的非 nil 元素;保留元素顺序。

a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
a.compact # => [0, false, "", [], {}]

相关信息: Array#compact!;另请参阅 用于删除的方法

static VALUE
rb_ary_compact(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_compact_bang(ary);
    return ary;
}
compact! → self 或 nil 点击以切换源代码

self 中删除所有 nil 元素;如果删除了任何元素,则返回 self;否则返回 nil

a = [nil, 0, nil, false, nil, '', nil, [], nil, {}]
a.compact! # => [0, false, "", [], {}]
a          # => [0, false, "", [], {}]
a.compact! # => nil

相关信息: Array#compact;另请参阅 用于删除的方法

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_arrays) → self 点击以切换源代码

other_arrays 中每个数组中的所有元素添加到 self;返回 self

a = [0, 1]
a.concat(['two', 'three'], [:four, :five], a)
# => [0, 1, "two", "three", :four, :five, 0, 1]

相关:请参阅 赋值方法

static VALUE
rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
{
    rb_ary_modify_check(ary);

    if (argc == 1) {
        rb_ary_concat(ary, argv[0]);
    }
    else if (argc > 1) {
        int i;
        VALUE args = rb_ary_hidden_new(argc);
        for (i = 0; i < argc; i++) {
            rb_ary_concat(args, argv[i]);
        }
        ary_append(ary, args);
    }

    ary_verify(ary);
    return ary;
}
count → integer 点击以切换源代码
count(object) → integer
count {|element| ... } → integer

返回指定元素的计数。

如果没有参数且没有代码块,则返回所有元素的计数。

[0, :one, 'two', 3, 3.0].count # => 5

如果给定参数 object,则返回与 object == 的元素的计数。

[0, :one, 'two', 3, 3.0].count(3) # => 2

如果没有参数且给定代码块,则对每个元素调用代码块;返回代码块返回真值的元素的计数。

[0, 1, 2, 3].count {|element| element > 1 } # => 2

如果给定参数 object 和代码块,则会发出警告,忽略该代码块,并返回与 object == 的元素的计数。

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long i, n = 0;

    if (rb_check_arity(argc, 0, 1) == 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 = argv[0];

        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(count = nil) {|element| ... } → nil 点击以切换源代码
cycle(count = nil) → new_enumerator

如果给定代码块,则可能会调用该代码块,具体取决于参数 count 的值;count 必须是 可转换为整数的对象,或者为 nil

count 为正数时,将对每个元素调用代码块,然后重复执行,直到执行了 count 次为止;返回 nil

output = []
[0, 1].cycle(2) {|element| output.push(element) } # => nil
output # => [0, 1, 0, 1]

count 为零或负数时,不会调用代码块。

[0, 1].cycle(0) {|element| fail 'Cannot happen' }  # => nil
[0, 1].cycle(-1) {|element| fail 'Cannot happen' } # => nil

countnil 时,将永远循环。

# Prints 0 and 1 forever.
[0, 1].cycle {|element| puts element }
[0, 1].cycle(nil) {|element| puts element }

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于迭代的方法

static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
{
    long n, i;

    rb_check_arity(argc, 0, 1);

    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
    if (argc == 0 || NIL_P(argv[0])) {
        n = -1;
    }
    else {
        n = NUM2LONG(argv[0]);
        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;
}
delete(object) → last_removed_object 点击以切换源代码
delete(object) {|element| ... } → last_removed_object 或 block_return

self 中删除零个或多个元素。

如果没有给定代码块,则从 self 中删除每个元素 ele,使得 ele == object;返回最后一个删除的元素。

a = [0, 1, 2, 2.0]
a.delete(2) # => 2.0
a           # => [0, 1]

如果没有删除任何元素,则返回 nil

a.delete(2) # => nil

如果给定代码块,则从 self 中删除每个元素 ele,使得 ele == object

如果找到任何此类元素,则忽略该代码块并返回最后一个删除的元素。

a = [0, 1, 2, 2.0]
a.delete(2) {|element| fail 'Cannot happen' } # => 2.0
a                                             # => [0, 1]

如果没有找到此类元素,则返回代码块的返回值。

a.delete(2) {|element| "Element #{element} not found." }
# => "Element 2 not found."

相关信息:请参阅 用于删除的方法

VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
    VALUE v = item;
    long i1, i2;

    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
        VALUE e = RARRAY_AREF(ary, i1);

        if (rb_equal(e, item)) {
            v = e;
            continue;
        }
        if (i1 != i2) {
            rb_ary_store(ary, i2, e);
        }
        i2++;
    }
    if (RARRAY_LEN(ary) == i2) {
        if (rb_block_given_p()) {
            return rb_yield(item);
        }
        return Qnil;
    }

    ary_resize_smaller(ary, i2);

    ary_verify(ary);
    return v;
}
delete_at(index) → removed_object 或 nil 点击以切换源代码

删除 self 中给定 index 处的元素,该 index 必须是 可转换为整数的对象

index 为非负数时,删除偏移量 index 处的元素。

a = [:foo, 'bar', 2]
a.delete_at(1) # => "bar"
a # => [:foo, 2]

index 为负数时,从数组末尾向后计数。

a = [:foo, 'bar', 2]
a.delete_at(-2) # => "bar"
a # => [:foo, 2]

index 超出范围时,返回 nil

a = [:foo, 'bar', 2]
a.delete_at(3)  # => nil
a.delete_at(-4) # => nil

相关信息:请参阅 用于删除的方法

static VALUE
rb_ary_delete_at_m(VALUE ary, VALUE pos)
{
    return rb_ary_delete_at(ary, NUM2LONG(pos));
}
delete_if {|element| ... } → self 点击以切换源代码
delete_if → new_numerator

如果给定代码块,则对 self 的每个元素调用该代码块;如果该代码块返回真值,则删除该元素;返回 self

a = [:foo, 'bar', 2, 'bat']
a.delete_if {|element| element.to_s.start_with?('b') } # => [:foo, 2]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于删除的方法

static VALUE
rb_ary_delete_if(VALUE ary)
{
    ary_verify(ary);
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    ary_reject_bang(ary);
    return ary;
}
difference(*other_arrays = []) → new_array 点击以切换源代码

返回一个新数组,该数组仅包含 self 中未在任何给定 other_arrays 中找到的元素;使用 eql? 比较项;保留 self 中的顺序。

[0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1]) # => [0, 2, 3]
[0, 1, 2, 3].difference([3, 0], [1, 3])     # => [2]
[0, 1, 2].difference([4])                   # => [0, 1, 2]
[0, 1, 2].difference                        # => [0, 1, 2]

如果没有给出任何参数,则返回 self 的副本。

相关信息: Array#-;另请参阅 用于组合的方法

static VALUE
rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
{
    VALUE ary_diff;
    long i, length;
    volatile VALUE t0;
    bool *is_hash = ALLOCV_N(bool, t0, argc);
    ary_diff = rb_ary_new();
    length = RARRAY_LEN(ary);

    for (i = 0; i < argc; i++) {
        argv[i] = to_ary(argv[i]);
        is_hash[i] = (length > SMALL_ARRAY_LEN && RARRAY_LEN(argv[i]) > SMALL_ARRAY_LEN);
        if (is_hash[i]) argv[i] = ary_make_hash(argv[i]);
    }

    for (i = 0; i < RARRAY_LEN(ary); i++) {
        int j;
        VALUE elt = rb_ary_elt(ary, i);
        for (j = 0; j < argc; j++) {
            if (is_hash[j]) {
                if (rb_hash_stlike_lookup(argv[j], RARRAY_AREF(ary, i), NULL))
                    break;
            }
            else {
                if (rb_ary_includes_by_eql(argv[j], elt)) break;
            }
        }
        if (j == argc) rb_ary_push(ary_diff, elt);
    }

    ALLOCV_END(t0);

    return ary_diff;
}
dig(index, *identifiers) → object 点击以切换源代码

查找并返回由 indexidentifiers 指定的嵌套对象中的对象;嵌套对象可以是各种类的实例。请参阅 Dig 方法

示例

a = [:foo, [:bar, :baz, [:bat, :bam]]]
a.dig(1) # => [:bar, :baz, [:bat, :bam]]
a.dig(1, 2) # => [:bat, :bam]
a.dig(1, 2, 0) # => :bat
a.dig(1, 2, 3) # => nil

相关:请参阅 获取方法

static 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(count) → new_array 点击以切换源代码

返回一个新数组,其中包含 self 中除了前 count 个元素之外的所有元素,其中 count 是一个非负整数;不会修改 self

示例

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

相关:请参阅 获取方法

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 (NIL_P(result)) result = rb_ary_new();
    return result;
}
drop_while {|element| ... } → new_array 点击以切换源
drop_while → new_enumerator

如果给定了代码块,则对 self 的每个连续元素调用该代码块;如果代码块返回 falsenil,则停止;返回一个新数组,其中省略了代码块返回真值的那些元素;不会修改 self

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

如果没有给定代码块,则返回一个新的 Enumerator

相关:请参阅 获取方法

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 {|element| ... } → self 点击以切换源
each → new_enumerator

如果给定了代码块,则迭代 self 的元素,并将每个元素传递给代码块;返回 self

a = [:foo, 'bar', 2]
a.each {|element|  puts "#{element.class} #{element}" }

输出

Symbol foo
String bar
Integer 2

允许在迭代期间修改数组。

a = [:foo, 'bar', 2]
a.each {|element| puts element; a.clear if element.to_s.start_with?('b') }

输出

foo
bar

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于迭代的方法

VALUE
rb_ary_each(VALUE ary)
{
    long i;
    ary_verify(ary);
    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| ... } → self 点击以切换源
each_index → new_enumerator

如果给定了代码块,则迭代 self 的元素,并将每个数组索引传递给代码块;返回 self

a = [:foo, 'bar', 2]
a.each_index {|index|  puts "#{index} #{a[index]}" }

输出

0 foo
1 bar
2 2

允许在迭代期间修改数组。

a = [:foo, 'bar', 2]
a.each_index {|index| puts index; a.clear if index > 0 }
a # => []

输出

0
1

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于迭代的方法

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 点击以切换源

如果 self 中的元素计数为零,则返回 true,否则返回 false

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_empty_p(VALUE ary)
{
    return RBOOL(RARRAY_LEN(ary) == 0);
}
eql?(other_array) → true or false 点击以切换源

如果 selfother_array 的大小相同,并且对于 self 中的每个索引 iself[i].eql?(other_array[i]),则返回 true

a0 = [:foo, 'bar', 2]
a1 = [:foo, 'bar', 2]
a1.eql?(a0) # => true

否则,返回 false

此方法与 Array#== 方法不同,后者使用 Object#== 方法进行比较。

相关信息:请参阅 用于查询的方法

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) → element 点击以切换源
fetch(index, default_value) → element 或 default_value
fetch(index) {|index| ... } → element 或 block_return_value

如果 index 在范围内,则返回 self 中偏移量为 index 的元素;index 必须是可转换为整数的对象

如果只给出单个参数 index 且没有代码块,则返回偏移量为 index 的元素。

a = [:foo, 'bar', 2]
a.fetch(1)   # => "bar"
a.fetch(1.1) # => "bar"

如果 index 为负数,则从数组末尾开始计数。

a = [:foo, 'bar', 2]
a.fetch(-1) # => 2
a.fetch(-2) # => "bar"

如果给出参数 indexdefault_value(可以是任何对象)且没有代码块,如果 index 超出范围,则返回 default_value

a = [:foo, 'bar', 2]
a.fetch(1, nil)  # => "bar"
a.fetch(3, :foo) # => :foo

如果给出参数 index 和一个代码块,如果索引在范围内(并且不调用代码块),则返回偏移量为 index 的元素;否则,使用索引调用代码块并返回其返回值。

a = [:foo, 'bar', 2]
a.fetch(1) {|index| raise 'Cannot happen' } # => "bar"
a.fetch(50) {|index| "Value for #{index}" } # => "Value for 50"

相关:请参阅 获取方法

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);
}
fetch_values(*indexes) → new_array 点击以切换源
fetch_values(*indexes) { |index| ... } → new_array

如果没有给出代码块,则返回一个新数组,其中包含 self 中偏移量由 indexes 指定的元素。每个 indexes 都必须是可转换为整数的对象

a = [:foo, :bar, :baz]
a.fetch_values(2, 0)   # => [:baz, :foo]
a.fetch_values(2.1, 0) # => [:baz, :foo]
a.fetch_values         # => []

对于负索引,从数组末尾向后计数。

a.fetch_values(-2, -1) # [:bar, :baz]

如果没有给出代码块,如果任何索引超出范围,则引发异常。

如果给出了代码块,对于每个索引:

  • 如果索引在范围内,则使用 self 的元素(如上所述)。

  • 否则,使用索引调用代码块并使用代码块的返回值。

示例

a = [:foo, :bar, :baz]
a.fetch_values(1, 0, 42, 777) { |index| index.to_s }
# => [:bar, :foo, "42", "777"]

相关:请参阅 获取方法

# File ruby_3_4_1/array.rb, line 210
def fetch_values(*indexes, &block)
  indexes.map! { |i| fetch(i, &block) }
  indexes
end
fill(object, start = nil, count = nil) → new_array 点击以切换源
fill(object, range) → new_array
fill(start = nil, count = nil) {|element| ... } → new_array
fill(range) {|element| ... } → new_array

替换 self 中的选定元素;可能会向 self 添加元素;始终返回 self(永远不是新数组)。

简而言之

# Non-negative start.
['a', 'b', 'c', 'd'].fill('-', 1, 2)          # => ["a", "-", "-", "d"]
['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]

# Extends with specified values if necessary.
['a', 'b', 'c', 'd'].fill('-', 3, 2)          # => ["a", "b", "c", "-", "-"]
['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]

# Fills with nils if necessary.
['a', 'b', 'c', 'd'].fill('-', 6, 2)          # => ["a", "b", "c", "d", nil, nil, "-", "-"]
['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]

# For negative start, counts backwards from the end.
['a', 'b', 'c', 'd'].fill('-', -3, 3)          # => ["a", "-", "-", "-"]
['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]

# Range.
['a', 'b', 'c', 'd'].fill('-', 1..2)          # => ["a", "-", "-", "d"]
['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]

当给出参数 startcount 时,它们选择要替换的 self 的元素;每个参数都必须是可转换为整数的对象(或 nil)。

  • start 指定要替换的第一个元素的从零开始的偏移量;nil 表示零。

  • count 是要替换的连续元素数量;nil 表示“其余全部”。

如果给出参数 object,则使用该对象进行所有替换。

o = Object.new           # => #<Object:0x0000014e7bff7600>
a = ['a', 'b', 'c', 'd'] # => ["a", "b", "c", "d"]
a.fill(o, 1, 2)
# => ["a", #<Object:0x0000014e7bff7600>, #<Object:0x0000014e7bff7600>, "d"]

如果给出了代码块,则为每个要替换的元素调用一次代码块;传递给代码块的值是要替换元素的索引(而不是元素本身);代码块的返回值替换该元素。

a = ['a', 'b', 'c', 'd']               # => ["a", "b", "c", "d"]
a.fill(1, 2) {|element| element.to_s } # => ["a", "1", "2", "d"]

对于参数 startcount

  • 如果 start 为非负数,则替换从偏移量 start 开始的 count 个元素。

    ['a', 'b', 'c', 'd'].fill('-', 0, 2) # => ["-", "-", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 1, 2) # => ["a", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 2, 2) # => ["a", "b", "-", "-"]
    
    ['a', 'b', 'c', 'd'].fill(0, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(1, 2) {|e| e.to_s } # => ["a", "1", "2", "d"]
    ['a', 'b', 'c', 'd'].fill(2, 2) {|e| e.to_s } # => ["a", "b", "2", "3"]
    

    如果需要,则扩展 self

    ['a', 'b', 'c', 'd'].fill('-', 3, 2) # => ["a", "b", "c", "-", "-"]
    ['a', 'b', 'c', 'd'].fill('-', 4, 2) # => ["a", "b", "c", "d", "-", "-"]
    
    ['a', 'b', 'c', 'd'].fill(3, 2) {|e| e.to_s } # => ["a", "b", "c", "3", "4"]
    ['a', 'b', 'c', 'd'].fill(4, 2) {|e| e.to_s } # => ["a", "b", "c", "d", "4", "5"]
    

    如果需要,则用 nil 填充。

    ['a', 'b', 'c', 'd'].fill('-', 5, 2) # => ["a", "b", "c", "d", nil, "-", "-"]
    ['a', 'b', 'c', 'd'].fill('-', 6, 2) # => ["a", "b", "c", "d", nil, nil, "-", "-"]
    
    ['a', 'b', 'c', 'd'].fill(5, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, "5", "6"]
    ['a', 'b', 'c', 'd'].fill(6, 2) {|e| e.to_s } # => ["a", "b", "c", "d", nil, nil, "6", "7"]
    

    如果 count 为非正数,则不执行任何操作。

    ['a', 'b', 'c', 'd'].fill('-', 2, 0)    # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
    
    ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' }    # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
    
  • 如果 start 为负数,则从 self 的末尾向后计数。

    ['a', 'b', 'c', 'd'].fill('-', -4, 3) # => ["-", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill('-', -3, 3) # => ["a", "-", "-", "-"]
    
    ['a', 'b', 'c', 'd'].fill(-4, 3) {|e| e.to_s } # => ["0", "1", "2", "d"]
    ['a', 'b', 'c', 'd'].fill(-3, 3) {|e| e.to_s } # => ["a", "1", "2", "3"]
    

    如果需要,则扩展 self

    ['a', 'b', 'c', 'd'].fill('-', -2, 3) # => ["a", "b", "-", "-", "-"]
    ['a', 'b', 'c', 'd'].fill('-', -1, 3) # => ["a", "b", "c", "-", "-", "-"]
    
    ['a', 'b', 'c', 'd'].fill(-2, 3) {|e| e.to_s } # => ["a", "b", "2", "3", "4"]
    ['a', 'b', 'c', 'd'].fill(-1, 3) {|e| e.to_s } # => ["a", "b", "c", "3", "4", "5"]
    

    如果 start 为负数且超出范围,则从 self 的开头开始。

    ['a', 'b', 'c', 'd'].fill('-', -5, 2) # => ["-", "-", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', -6, 2) # => ["-", "-", "c", "d"]
    
    ['a', 'b', 'c', 'd'].fill(-5, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(-6, 2) {|e| e.to_s } # => ["0", "1", "c", "d"]
    

    如果 count 为非正数,则不执行任何操作。

    ['a', 'b', 'c', 'd'].fill('-', -2, 0)  # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', -2, -1) # => ["a", "b", "c", "d"]
    
    ['a', 'b', 'c', 'd'].fill(-2, 0) {|e| fail 'Cannot happen' }  # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(-2, -1) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
    

当给出参数 range 时,它必须是一个 Range 对象,其成员为数值;它的 beginend 值确定要替换的 self 的元素。

  • 如果 beginend 均为正数,则它们指定要替换的第一个和最后一个元素。

    ['a', 'b', 'c', 'd'].fill('-', 1..2)          # => ["a", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill(1..2) {|e| e.to_s } # => ["a", "1", "2", "d"]
    

    如果 end 小于 begin,则不替换任何元素。

    ['a', 'b', 'c', 'd'].fill('-', 2..1)          # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
    
  • 如果其中一个为负数(或两者均为负数),则从 self 的末尾向后计数。

    ['a', 'b', 'c', 'd'].fill('-', -3..2)  # => ["a", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 1..-2)  # => ["a", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
    
    ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s }  # => ["a", "1", "2", "d"]
    ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s }  # => ["a", "1", "2", "d"]
    ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
    
  • 如果排除了 end 值(请参阅 Range#exclude_end?),则省略最后一个替换。

    ['a', 'b', 'c', 'd'].fill('-', 1...2)  # => ["a", "-", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
    
    ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s }  # => ["a", "1", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
    
  • 如果范围是无限的(请参阅 无限范围),则替换到 self 末尾的元素。

    ['a', 'b', 'c', 'd'].fill('-', 1..)          # => ["a", "-", "-", "-"]
    ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
    
  • 如果范围是无始的(请参阅 无始范围),则替换从 self 开头的元素。

    ['a', 'b', 'c', 'd'].fill('-', ..2)          # => ["-", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill(..2) {|e| e.to_s } # => ["0", "1", "2", "d"]
    

相关:请参阅 赋值方法

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 (UNDEF_P(item)) {
        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;
}
filter {|element| ... } → new_array
filter → new_enumerator

如果给定了代码块,则对 self 的每个元素调用该代码块;返回一个新数组,其中包含 self 中代码块返回真值的那些元素。

a = [:foo, 'bar', 2, :bam]
a.select {|element| element.to_s.start_with?('b') }
# => ["bar", :bam]

如果没有给定代码块,则返回一个新的 Enumerator

相关:请参阅 获取方法

别名:select
filter! {|element| ... } → self 或 nil
filter! → new_enumerator

如果给定了代码块,则对 self 的每个元素调用该代码块;从 self 中删除代码块返回 falsenil 的那些元素。

如果删除了任何元素,则返回 self

a = [:foo, 'bar', 2, :bam]
a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]

如果未删除任何元素,则返回 nil

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于删除的方法

别名:select!
find_index -> new_enumerator 点击以切换源

返回指定元素的从零开始的整数索引,或 nil

如果只给出参数 object,则返回第一个元素 element 的索引,其中 object == element

a = [:foo, 'bar', 2, 'bar']
a.index('bar') # => 1

如果没有找到此类元素,则返回 nil

如果只给出一个代码块,则对每个连续元素调用代码块;返回代码块返回真值的第一个元素的索引。

a = [:foo, 'bar', 2, 'bar']
a.index {|element| element == 'bar' } # => 1

如果代码块从未返回真值,则返回 nil

如果没有给出参数或代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
    VALUE val;
    long i;

    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");
    for (i=0; i<RARRAY_LEN(ary); i++) {
        VALUE e = RARRAY_AREF(ary, i);
        if (rb_equal(e, val)) {
            return LONG2NUM(i);
        }
    }
    return Qnil;
}
也别名为:index
first → object 或 nil 点击以切换源
first(count) → new_array

self 返回元素,或 nil;不会修改 self

如果没有给出参数,则返回第一个元素(如果可用)。

a = [:foo, 'bar', 2]
a.first # => :foo
a # => [:foo, "bar", 2]

如果 self 为空,则返回 nil

[].first # => nil

如果给出了非负整数参数 count,则在一个新数组中返回前 count 个元素(如果可用)。

a.first(0)  # => []
a.first(2)  # => [:foo, "bar"]
a.first(50) # => [:foo, "bar", 2]

相关信息:请参阅 用于查询的方法

# File ruby_3_4_1/array.rb, line 129
def first n = unspecified = true
  if Primitive.mandatory_only?
    Primitive.attr! :leaf
    Primitive.cexpr! %q{ ary_first(self) }
  else
    if unspecified
      Primitive.cexpr! %q{ ary_first(self) }
    else
      Primitive.cexpr! %q{  ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_FIRST) }
    end
  end
end
flatten(depth = nil) → new_array 点击以切换源

返回一个新数组,该数组是 self 的递归扁平化,递归深度为 depth 层;depth 必须是可转换为整数的对象nil。在每个递归级别:

  • 每个是数组的元素都将被“扁平化”(即,替换为其单独的数组元素)。

  • 每个不是数组的元素都保持不变(即使该元素是具有实例方法 flatten 的对象)。

如果给出非负整数参数 depth,则递归地扁平化 depth 层。

a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
a              # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
a.flatten(0)   # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
a.flatten(1  ) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.flatten(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.flatten(2)   # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.flatten(3)   # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]

如果给出 nil 或负数 depth,则扁平化所有层。

a.flatten     # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.flatten(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]

相关:Array#flatten!;另请参阅转换方法

static VALUE
rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
{
    int level = -1;
    VALUE result;

    if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0])) {
        level = NUM2INT(argv[0]);
        if (level == 0) return ary_make_shared_copy(ary);
    }

    result = flatten(ary, level);
    if (result == ary) {
        result = ary_make_shared_copy(ary);
    }

    return result;
}
flatten!(depth = nil) → self 或 nil 点击以切换源

self 作为 self 的递归扁平化返回,递归深度为 depth 层;depth 必须是可转换为整数的对象,或 nil。在每个递归级别:

  • 每个是数组的元素都将被“扁平化”(即,替换为其单独的数组元素)。

  • 每个不是数组的元素都保持不变(即使该元素是具有实例方法 flatten 的对象)。

如果没有扁平化任何元素,则返回 nil

如果给出非负整数参数 depth,则递归地扁平化 depth 层。

a = [ 0, [ 1, [2, 3], 4 ], 5, {foo: 0}, Set.new([6, 7]) ]
a                   # => [0, [1, [2, 3], 4], 5, {:foo=>0}, #<Set: {6, 7}>]
a.dup.flatten!(1)   # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.dup.flatten!(1.1) # => [0, 1, [2, 3], 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.dup.flatten!(2)   # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.dup.flatten!(3)   # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]

如果给出 nil 或负数参数 depth,则扁平化所有层。

a.dup.flatten!     # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]
a.dup.flatten!(-1) # => [0, 1, 2, 3, 4, 5, {:foo=>0}, #<Set: {6, 7}>]

相关:Array#flatten;另请参阅赋值方法

static VALUE
rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
{
    int mod = 0, level = -1;
    VALUE result, lv;

    lv = (rb_check_arity(argc, 0, 1) ? argv[0] : Qnil);
    rb_ary_modify_check(ary);
    if (!NIL_P(lv)) level = NUM2INT(lv);
    if (level == 0) return Qnil;

    result = flatten(ary, level);
    if (result == ary) {
        return Qnil;
    }
    if (!(mod = ARY_EMBED_P(result))) rb_ary_freeze(result);
    rb_ary_replace(ary, result);
    if (mod) ARY_SET_EMBED_LEN(result, 0);

    return ary;
}
freeze → self 点击以切换源

冻结 self(如果尚未冻结);返回 self

a = []
a.frozen? # => false
a.freeze
a.frozen? # => true

不得对 self 进行任何进一步的更改;如果尝试更改,则引发 FrozenError

相关:Kernel#frozen?

VALUE
rb_ary_freeze(VALUE ary)
{
    RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));

    if (OBJ_FROZEN(ary)) return ary;

    if (!ARY_EMBED_P(ary) && !ARY_SHARED_P(ary) && !ARY_SHARED_ROOT_P(ary)) {
        ary_shrink_capa(ary);
    }

    return rb_obj_freeze(ary);
}
hash → integer 点击以切换源

返回 self 的整数哈希值。

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

['a', 'b'].hash == ['a', 'b'].hash # => true
['a', 'b'].hash == ['a', 'c'].hash # => false
['a', 'b'].hash == ['a'].hash      # => false
static VALUE
rb_ary_hash(VALUE ary)
{
    return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
}
include?(object) → true 或 false 点击切换源码

返回 self 中是否存在某个元素 element,使得 object == element

[0, 1, 2].include?(2)   # => true
[0, 1, 2].include?(2.0) # => true
[0, 1, 2].include?(2.1) # => false

相关信息:请参阅 用于查询的方法

VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
    long i;
    VALUE e;

    for (i=0; i<RARRAY_LEN(ary); i++) {
        e = RARRAY_AREF(ary, i);
        if (rb_equal(e, item)) {
            return Qtrue;
        }
    }
    return Qfalse;
}
index(object) → 整数 或 nil
index {|element| ... } → 整数 或 nil
index → 新的枚举器

返回指定元素的从零开始的整数索引,或 nil

如果只给出参数 object,则返回第一个元素 element 的索引,其中 object == element

a = [:foo, 'bar', 2, 'bar']
a.index('bar') # => 1

如果没有找到此类元素,则返回 nil

如果只给出一个代码块,则对每个连续元素调用代码块;返回代码块返回真值的第一个元素的索引。

a = [:foo, 'bar', 2, 'bar']
a.index {|element| element == 'bar' } # => 1

如果代码块从未返回真值,则返回 nil

如果没有给出参数或代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于查询的方法

别名: find_index
initialize_copy(other_array) → self 点击切换源码

self 的元素替换为 other_array 的元素,other_array 必须是 可转换为数组的对象;返回 self

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

相关:请参阅 赋值方法

VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
    rb_ary_modify_check(copy);
    orig = to_ary(orig);
    if (copy == orig) return copy;

    rb_ary_reset(copy);

    /* orig has enough space to embed the contents of orig. */
    if (RARRAY_LEN(orig) <= ary_embed_capa(copy)) {
        RUBY_ASSERT(ARY_EMBED_P(copy));
        ary_memcpy(copy, 0, RARRAY_LEN(orig), RARRAY_CONST_PTR(orig));
        ARY_SET_EMBED_LEN(copy, RARRAY_LEN(orig));
    }
    /* orig is embedded but copy does not have enough space to embed the
     * contents of orig. */
    else if (ARY_EMBED_P(orig)) {
        long len = ARY_EMBED_LEN(orig);
        VALUE *ptr = ary_heap_alloc_buffer(len);

        FL_UNSET_EMBED(copy);
        ARY_SET_PTR(copy, ptr);
        ARY_SET_LEN(copy, len);
        ARY_SET_CAPA(copy, len);

        // No allocation and exception expected that could leave `copy` in a
        // bad state from the edits above.
        ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
    }
    /* Otherwise, orig is on heap and copy does not have enough space to embed
     * the contents of orig. */
    else {
        VALUE shared_root = ary_make_shared(orig);
        FL_UNSET_EMBED(copy);
        ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
        ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
        rb_ary_set_shared(copy, shared_root);
    }
    ary_verify(copy);
    return copy;
}
别名:replace
insert(index, *objects) → self 点击切换源码

将给定的 objects 作为 self 的元素插入;返回 self

index 为非负数时,将 objects 插入到偏移量为 index 的元素之前

a = ['a', 'b', 'c']     # => ["a", "b", "c"]
a.insert(1, :x, :y, :z) # => ["a", :x, :y, :z, "b", "c"]

如果 index 超出数组范围 (index >= self.size),则扩展数组

a = ['a', 'b', 'c']     # => ["a", "b", "c"]
a.insert(5, :x, :y, :z) # => ["a", "b", "c", nil, nil, :x, :y, :z]

index 为负数时,将 objects 插入到偏移量为 index + self.size 的元素之后

a = ['a', 'b', 'c']      # => ["a", "b", "c"]
a.insert(-2, :x, :y, :z) # => ["a", "b", :x, :y, :z, "c"]

如果没有给出 objects,则不执行任何操作

a = ['a', 'b', 'c'] # => ["a", "b", "c"]
a.insert(1)         # => ["a", "b", "c"]
a.insert(50)        # => ["a", "b", "c"]
a.insert(-50)       # => ["a", "b", "c"]

如果给出了 objects 并且 index 为负数且超出范围,则引发 IndexError 错误。

相关:请参阅 赋值方法

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);
    pos = NUM2LONG(argv[0]);
    if (argc == 1) return ary;
    if (pos == -1) {
        pos = RARRAY_LEN(ary);
    }
    else if (pos < 0) {
        long minpos = -RARRAY_LEN(ary) - 1;
        if (pos < minpos) {
            rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
                     pos, minpos);
        }
        pos++;
    }
    rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
    return ary;
}
inspect → new_string 点击切换源码

返回通过对每个数组元素调用方法 #inspect 形成的新字符串

a = [:foo, 'bar', 2]
a.inspect # => "[:foo, \"bar\", 2]"

相关:请参阅 用于转换的方法

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);
}
别名: to_s
intersect?(other_array) → true 或 false 点击切换源码

返回 other_array 是否至少有一个元素与 self 的某个元素 #eql?

[1, 2, 3].intersect?([3, 4, 5]) # => true
[1, 2, 3].intersect?([4, 5, 6]) # => false

每个元素必须正确实现方法 #hash

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_intersect_p(VALUE ary1, VALUE ary2)
{
    VALUE hash, v, result, shorter, longer;
    st_data_t vv;
    long i;

    ary2 = to_ary(ary2);
    if (RARRAY_LEN(ary1) == 0 || RARRAY_LEN(ary2) == 0) return Qfalse;

    if (RARRAY_LEN(ary1) <= SMALL_ARRAY_LEN && RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
        for (i=0; i<RARRAY_LEN(ary1); i++) {
            v = RARRAY_AREF(ary1, i);
            if (rb_ary_includes_by_eql(ary2, v)) return Qtrue;
        }
        return Qfalse;
    }

    shorter = ary1;
    longer = ary2;
    if (RARRAY_LEN(ary1) > RARRAY_LEN(ary2)) {
        longer = ary1;
        shorter = ary2;
    }

    hash = ary_make_hash(shorter);
    result = Qfalse;

    for (i=0; i<RARRAY_LEN(longer); i++) {
        v = RARRAY_AREF(longer, i);
        vv = (st_data_t)v;
        if (rb_hash_stlike_lookup(hash, vv, 0)) {
            result = Qtrue;
            break;
        }
    }

    return result;
}
intersection(*other_arrays) → new_array 点击切换源码

返回一个新数组,其中包含 self 中与给定的每个 other_arrays 中至少一个元素 #eql? 的每个元素;重复元素被省略

[0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3]) # => [0, 1]

每个元素必须正确实现方法 #hash

保留来自 self 的顺序

[0, 1, 2].intersection([2, 1, 0]) # => [0, 1, 2]

如果没有给出任何参数,则返回 self 的副本。

相关:请参阅 组合方法

static VALUE
rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = rb_ary_dup(ary);
    int i;

    for (i = 0; i < argc; i++) {
        result = rb_ary_and(result, argv[i]);
    }

    return result;
}
join(separator = $,) → new_string 点击切换源码

返回通过连接 self 的转换元素形成的新字符串;对于每个元素 element

  • 如果 elementkind_of?(Array),则使用 element.join(separator) 递归转换。

  • 否则,使用 element.to_s 进行转换。

如果没有给出参数,则使用输出字段分隔符 $, 进行连接

a = [:foo, 'bar', 2]
$, # => nil
a.join # => "foobar2"

如果给出了字符串参数 separator,则使用该分隔符进行连接

a = [:foo, 'bar', 2]
a.join("\n") # => "foo\nbar\n2"

递归连接嵌套数组

a = [:foo, [:bar, [:baz, :bat]]]
a.join # => "foobarbazbat"

相关:请参阅 用于转换的方法

static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE sep;

    if (rb_check_arity(argc, 0, 1) == 0 || NIL_P(sep = argv[0])) {
        sep = rb_output_fs;
        if (!NIL_P(sep)) {
            rb_category_warn(RB_WARN_CATEGORY_DEPRECATED, "$, is set to non-nil value");
        }
    }

    return rb_ary_join(ary, sep);
}
keep_if {|element| ... } → self 点击切换源码
keep_if → 新的枚举器

如果给出了块,则对 self 的每个元素调用该块;如果该块没有返回真值,则从 self 中删除该元素

a = [:foo, 'bar', 2, :bam]
a.keep_if {|element| element.to_s.start_with?('b') } # => ["bar", :bam]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于删除的方法

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 → last_object 或 nil 点击切换源码
last(count) → new_array

self 返回元素,或者 nilself 不会被修改。

如果没有给出参数,则返回最后一个元素,如果 self 为空,则返回 nil

a = [:foo, 'bar', 2]
a.last # => 2
a # => [:foo, "bar", 2]
[].last # => nil

如果给出了非负整数参数 count,则返回一个新数组,其中包含 self 的尾部 count 个元素(如果可用)

a = [:foo, 'bar', 2]
a.last(2)  # => ["bar", 2]
a.last(50) # => [:foo, "bar", 2]
a.last(0)  # => []
[].last(3) # => []

相关:请参阅 获取方法

# File ruby_3_4_1/array.rb, line 166
def last n = unspecified = true
  if Primitive.mandatory_only?
    Primitive.attr! :leaf
    Primitive.cexpr! %q{ ary_last(self) }
  else
    if unspecified
      Primitive.cexpr! %q{ ary_last(self) }
    else
      Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_LAST) }
    end
  end
end
length → 整数 点击切换源码

返回 self 中元素的计数

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

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}
别名: size
map {|element| ... } → new_array
map → 新的枚举器

如果给定代码块,则对 self 的每个元素调用该代码块;返回一个新数组,其元素是来自代码块的返回值。

a = [:foo, 'bar', 2]
a1 = a.map {|element| element.class }
a1 # => [Symbol, String, Integer]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息: collect!;另请参阅 用于转换的方法

别名:collect
别名: collect
map! {|element| ... } → new_array
map! → 新的枚举器

如果给定代码块,则对 self 的每个元素调用该代码块,并将该元素替换为代码块的返回值;返回 self

a = [:foo, 'bar', 2]
a.map! { |element| element.class } # => [Symbol, String, Integer]

如果没有给定代码块,则返回一个新的 Enumerator

相关信息: collect;另请参阅 用于转换的方法

别名: collect!
max → element 点击切换源码
max(count) → new_array
max {|a, b| ... } → element
max(count) {|a, b| ... } → new_array

返回以下之一

  • 来自 self 的最大值元素。

  • 来自 self 的最大值元素的新数组。

不修改 self

如果没有给出块,则 self 中的每个元素必须使用数字响应方法 #<=>

如果没有参数且没有块,则返回根据方法 #<=> 具有最大值的 self 中的元素

[1, 0, 3, 2].max # => 3

如果给出了非负数值参数 count 且没有块,则返回一个新数组,该数组最多包含 count 个元素,并按照方法 #<=> 降序排列

[1, 0, 3, 2].max(3)   # => [3, 2, 1]
[1, 0, 3, 2].max(3.0) # => [3, 2, 1]
[1, 0, 3, 2].max(9)   # => [3, 2, 1, 0]
[1, 0, 3, 2].max(0)   # => []

如果给出了块,则该块必须返回一个数字。

如果给出了块且没有参数,则调用该块 self.size - 1 次以比较元素;返回根据该块具有最大值的元素

['0', '', '000', '00'].max {|a, b| a.size <=> b.size }
# => "000"

如果给出了非负数值参数 count 且有一个块,则返回一个新数组,该数组最多包含 count 个元素,并根据该块降序排列

['0', '', '000', '00'].max(2) {|a, b| a.size <=> b.size }
# => ["000", "00"]

相关:请参阅 获取方法

static VALUE
rb_ary_max(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = Qundef, v;
    VALUE num;
    long i;

    if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
       return rb_nmin_run(ary, num, 0, 1, 1);

    const long n = RARRAY_LEN(ary);
    if (rb_block_given_p()) {
        for (i = 0; i < RARRAY_LEN(ary); i++) {
           v = RARRAY_AREF(ary, i);
           if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
               result = v;
           }
        }
    }
    else if (n > 0) {
        result = RARRAY_AREF(ary, 0);
        if (n > 1) {
            if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
                return ary_max_opt_fixnum(ary, 1, result);
            }
            else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
                return ary_max_opt_string(ary, 1, result);
            }
            else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
                return ary_max_opt_float(ary, 1, result);
            }
            else {
                return ary_max_generic(ary, 1, result);
            }
        }
    }
    if (UNDEF_P(result)) return Qnil;
    return result;
}
min → element 点击切换源码
min(count) → new_array
min {|a, b| ... } → element
min(count) {|a, b| ... } → new_array

返回以下之一

  • 来自 self 的最小值元素。

  • 来自 self 的最小值元素的新数组。

不修改 self

如果没有给出块,则 self 中的每个元素必须使用数字响应方法 #<=>

如果没有参数且没有块,则返回根据方法 #<=> 具有最小值的 self 中的元素

[1, 0, 3, 2].min # => 0

如果给出了非负数值参数 count 且没有块,则返回一个新数组,该数组最多包含 count 个元素,并按照方法 #<=> 升序排列

[1, 0, 3, 2].min(3)   # => [0, 1, 2]
[1, 0, 3, 2].min(3.0) # => [0, 1, 2]
[1, 0, 3, 2].min(9)   # => [0, 1, 2, 3]
[1, 0, 3, 2].min(0)   # => []

如果给出了块,则该块必须返回一个数字。

如果给出了块且没有参数,则调用该块 self.size - 1 次以比较元素;返回根据该块具有最小值的元素

['0', '', '000', '00'].min {|a, b| a.size <=> b.size }
# => ""

如果给出了非负数值参数 count 且有一个块,则返回一个新数组,该数组最多包含 count 个元素,并根据该块升序排列

['0', '', '000', '00'].min(2) {|a, b| a.size <=> b.size }
# => ["", "0"]

相关:请参阅 获取方法

static VALUE
rb_ary_min(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = Qundef, v;
    VALUE num;
    long i;

    if (rb_check_arity(argc, 0, 1) && !NIL_P(num = argv[0]))
       return rb_nmin_run(ary, num, 0, 0, 1);

    const long n = RARRAY_LEN(ary);
    if (rb_block_given_p()) {
        for (i = 0; i < RARRAY_LEN(ary); i++) {
           v = RARRAY_AREF(ary, i);
           if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
               result = v;
           }
        }
    }
    else if (n > 0) {
        result = RARRAY_AREF(ary, 0);
        if (n > 1) {
            if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
                return ary_min_opt_fixnum(ary, 1, result);
            }
            else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
                return ary_min_opt_string(ary, 1, result);
            }
            else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
                return ary_min_opt_float(ary, 1, result);
            }
            else {
                return ary_min_generic(ary, 1, result);
            }
        }
    }
    if (UNDEF_P(result)) return Qnil;
    return result;
}
minmax → array 点击切换源码
minmax {|a, b| ... } → array

返回一个包含来自 self 的最小值和最大值元素的 2 个元素的数组;不修改 self

如果没有给出块,则使用方法 #<=> 确定最小值和最大值

[1, 0, 3, 2].minmax # => [0, 3]

如果给出了块,则该块必须返回一个数字;调用该块 self.size - 1 次以比较元素;返回根据该块具有最小值和最大值的元素

['0', '', '000', '00'].minmax {|a, b| a.size <=> b.size }
# => ["", "000"]

相关:请参阅 获取方法

static VALUE
rb_ary_minmax(VALUE ary)
{
    if (rb_block_given_p()) {
        return rb_call_super(0, NULL);
    }
    return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
}
none? → true 或 false 点击切换源码
none?(object) → true 或 false
none? {|element| ... } → true 或 false

如果 self 的任何元素都不满足给定条件,则返回 true,否则返回 false

如果没有给出块并且没有参数,则如果 self 没有真值元素,则返回 true,否则返回 false

[nil, false].none?    # => true
[nil, 0, false].none? # => false
[].none?              # => true

如果给出了参数 object,则如果对于任何元素 elementobject === element,则返回 false;否则返回 true

['food', 'drink'].none?(/bar/) # => true
['food', 'drink'].none?(/foo/) # => false
[].none?(/foo/)                # => true
[0, 1, 2].none?(3)             # => true
[0, 1, 2].none?(1)             # => false

如果给出了块,则对 self 中的每个元素调用该块;如果该块没有返回真值,则返回 true,否则返回 false

[0, 1, 2].none? {|element| element > 3 } # => true
[0, 1, 2].none? {|element| element > 1 } # => false

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);

    rb_check_arity(argc, 0, 1);
    if (!len) return Qtrue;
    if (argc) {
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) return Qfalse;
        }
    }
    else if (!rb_block_given_p()) {
        for (i = 0; i < len; ++i) {
            if (RTEST(RARRAY_AREF(ary, i))) return Qfalse;
        }
    }
    else {
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) return Qfalse;
        }
    }
    return Qtrue;
}
one? → true 或 false 点击切换源码
one? {|element| ... } → true 或 false
one?(object) → true 或 false

如果 self 中只有一个元素满足给定条件,则返回 true

如果没有给出块并且没有参数,则如果 self 只有一个真值元素,则返回 true,否则返回 false

[nil, 0].one? # => true
[0, 0].one? # => false
[nil, nil].one? # => false
[].one? # => false

如果给出了块,则对 self 中的每个元素调用该块;如果该块对于只有一个元素返回真值,则返回 true,否则返回 false

[0, 1, 2].one? {|element| element > 0 } # => false
[0, 1, 2].one? {|element| element > 1 } # => true
[0, 1, 2].one? {|element| element > 2 } # => false

如果给出了参数 object,则如果对于只有一个元素 elementobject === element,则返回 true;否则返回 false

[0, 1, 2].one?(0) # => true
[0, 0, 1].one?(0) # => false
[1, 1, 2].one?(0) # => false
['food', 'drink'].one?(/bar/) # => false
['food', 'drink'].one?(/foo/) # => true
[].one?(/foo/) # => false

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);
    VALUE result = Qfalse;

    rb_check_arity(argc, 0, 1);
    if (!len) return Qfalse;
    if (argc) {
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (RTEST(rb_funcall(argv[0], idEqq, 1, RARRAY_AREF(ary, i)))) {
                if (result) return Qfalse;
                result = Qtrue;
            }
        }
    }
    else if (!rb_block_given_p()) {
        for (i = 0; i < len; ++i) {
            if (RTEST(RARRAY_AREF(ary, i))) {
                if (result) return Qfalse;
                result = Qtrue;
            }
        }
    }
    else {
        for (i = 0; i < RARRAY_LEN(ary); ++i) {
            if (RTEST(rb_yield(RARRAY_AREF(ary, i)))) {
                if (result) return Qfalse;
                result = Qtrue;
            }
        }
    }
    return result;
}
pack(template, buffer: nil) → string 点击切换源码

self 中的每个元素格式化为二进制字符串;返回该字符串。请参阅 打包数据

# File ruby_3_4_1/pack.rb, line 7
def pack(fmt, buffer: nil)
  Primitive.pack_pack(fmt, buffer)
end
permutation(count = self.size) {|permutation| ... } → self 点击切换源码
permutation(count = self.size) → 新的枚举器

迭代 self 元素的排列;排列的顺序是不确定的。

如果给出了块和一个范围内的正整数参数 count (0 < count <= self.size),则对大小为 countself 的每个排列调用该块;返回 self

a = [0, 1, 2]
perms = []
a.permutation(1) {|perm| perms.push(perm) }
perms # => [[0], [1], [2]]

perms = []
a.permutation(2) {|perm| perms.push(perm) }
perms # => [[0, 1], [0, 2], [1, 0], [1, 2], [2, 0], [2, 1]]

perms = []
a.permutation(3) {|perm| perms.push(perm) }
perms # => [[0, 1, 2], [0, 2, 1], [1, 0, 2], [1, 2, 0], [2, 0, 1], [2, 1, 0]]

count 为零时,将用新的空数组调用代码块一次。

perms = []
a.permutation(0) {|perm| perms.push(perm) }
perms # => [[]]

count 超出范围(负数或大于 self.size)时,不会调用该块

a.permutation(-1) {|permutation| fail 'Cannot happen' }
a.permutation(4) {|permutation| fail 'Cannot happen' }

如果没有给定代码块,则返回一个新的 Enumerator

相关:迭代方法

static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
    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 */
    r = n;
    if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
        r = NUM2LONG(argv[0]);            /* 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 → object 或 nil 点击切换源码
pop(count) → new_array

删除并返回 self 的尾部元素。

如果没有给出参数,则删除并返回最后一个元素(如果可用);否则返回 nil

a = [:foo, 'bar', 2]
a.pop  # => 2
a      # => [:foo, "bar"]
[].pop # => nil

如果给出了非负整数参数 count,则返回一个新数组,其中包含 self 的尾部 count 个元素(如果可用)

a = [:foo, 'bar', 2]
a.pop(2) # => ["bar", 2]
a        # => [:foo]

a = [:foo, 'bar', 2]
a.pop(50) # => [:foo, "bar", 2]
a         # => []

相关:Array#push;另请参阅 用于删除的方法

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));
    ary_verify(ary);
    return result;
}
prepend(*objects) → self

将给定的 objects 添加到 self 的开头

a = [:foo, 'bar', 2]
a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]

相关:Array#shift;另请参阅 用于赋值的方法

别名: unshift
product(*other_arrays) → new_array 点击切换源代码
product(*other_arrays) {|combination| ... } → self

计算所有数组(包括 selfother_arrays)中元素的组合。

  • 组合的数量是所有数组(包括 selfother_arrays)大小的乘积。

  • 返回的组合顺序是不确定的。

如果没有给出块,则返回作为数组的数组的组合。

p = [0, 1].product([2, 3])
# => [[0, 2], [0, 3], [1, 2], [1, 3]]
p.size # => 4
p = [0, 1].product([2, 3], [4, 5])
# => [[0, 2, 4], [0, 2, 5], [0, 3, 4], [0, 3, 5], [1, 2, 4], [1, 2, 5], [1, 3, 4], [1, 3,...
p.size # => 8

如果 self 或任何参数为空,则返回一个空数组。

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

如果没有给出参数,则返回一个包含 1 个元素数组的数组,每个数组包含 self 的一个元素。

a.product # => [[0], [1], [2]]

如果给出了块,则用每个组合调用该块;返回 self

p = []
[0, 1].product([2, 3]) {|combination| p.push(combination) }
p # => [[0, 2], [0, 3], [1, 2], [1, 3]]

如果 self 或任何参数为空,则不调用该块。

[].product([2, 3], [4, 5]) {|combination| fail 'Cannot happen' }
# => []
[0, 1].product([2, 3], []) {|combination| fail 'Cannot happen' }
# => [0, 1]

如果没有给出参数,则使用 self 的每个元素作为 1 个元素的数组来调用该块。

p = []
[0, 1].product {|combination| p.push(combination) }
p # => [[0], [1]]

相关:请参阅 组合方法

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 = rb_ary_hidden_new(n);
    volatile VALUE t1 = Qundef;
    VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
    int *counters = ALLOCV_N(int, t1, n); /* 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);

    /* 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, RARRAY_SHARED_ROOT_FLAG);
            rb_yield(subarray);
            if (!FL_TEST(t0, RARRAY_SHARED_ROOT_FLAG)) {
                rb_raise(rb_eRuntimeError, "product reentered");
            }
            else {
                FL_UNSET(t0, RARRAY_SHARED_ROOT_FLAG);
            }
        }
        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:
    ALLOCV_END(t1);

    return NIL_P(result) ? ary : result;
}
push(*objects) → self 点击切换源代码

objects 中的每个参数追加到 self;返回 self

a = [:foo, 'bar', 2] # => [:foo, "bar", 2]
a.push(:baz, :bat)   # => [:foo, "bar", 2, :baz, :bat]

即使参数是另一个数组,也会将每个参数作为单个元素追加。

a = [:foo, 'bar', 2]               # => [:foo, "bar", 2]
a.push([:baz, :bat], [:bam, :bad]) # => [:foo, "bar", 2, [:baz, :bat], [:bam, :bad]]

相关:请参阅 赋值方法

static VALUE
rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
{
    return rb_ary_cat(ary, argv, argc);
}
别名为:append
rassoc(object) → found_array or nil 点击切换源代码

返回 self 中第一个元素 ele,使得 ele 是一个数组且 ele[1] == object

a = [{foo: 0}, [2, 4], [4, 5, 6], [4, 5]]
a.rassoc(4) # => [2, 4]
a.rassoc(5) # => [4, 5, 6]

如果未找到此类元素,则返回 nil

相关:Array#assoc;另请参阅 用于获取的方法

VALUE
rb_ary_rassoc(VALUE ary, VALUE value)
{
    long i;
    VALUE v;

    for (i = 0; i < RARRAY_LEN(ary); ++i) {
        v = rb_check_array_type(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 {|element| ... } → new_array 点击切换源代码
reject → new_enumerator

如果给出了块,则返回一个新数组,该数组的元素是 self 中所有使该块返回 falsenil 的元素。

a = [:foo, 'bar', 2, 'bat']
a1 = a.reject {|element| element.to_s.start_with?('b') }
a1 # => [:foo, 2]

如果没有给定代码块,则返回一个新的 Enumerator

相关:用于获取的方法

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! {|element| ... } → self or nil 点击切换源代码
reject! → new_enumerator

如果给出了块,则使用 self 的每个元素调用该块;删除每个使该块返回真值的元素。

如果删除了任何元素,则返回 self

a = [:foo, 'bar', 2, 'bat']
a.reject! {|element| element.to_s.start_with?('b') } # => [:foo, 2]

如果没有删除元素,则返回 nil

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于删除的方法

static VALUE
rb_ary_reject_bang(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    rb_ary_modify(ary);
    return ary_reject_bang(ary);
}
repeated_combination(size) {|combination| ... } → self 点击切换源代码
repeated_combination(size) → new_enumerator

如果给出了块,则使用 self 元素的长度为 size 的每个重复组合调用该块;每个组合都是一个数组;返回 self。组合的顺序是不确定的。

如果给出了一个正整数参数 size,则使用 self 元素的每个 size 元组重复组合调用该块。组合的数量是 (size+1)(size+2)/2

示例

  • size 为 1

    c = []
    [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
    c # => [[0], [1], [2]]
    
  • size 为 2

    c = []
    [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
    c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
    

如果 size 为零,则使用一个空数组调用该块一次。

如果 size 为负数,则不调用该块。

[0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }

如果没有给定代码块,则返回一个新的 Enumerator

相关:请参阅 组合方法

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(size) {|permutation| ... } → self 点击切换源代码
repeated_permutation(size) → new_enumerator

如果给出了块,则使用 self 元素的长度为 size 的每个重复排列调用该块;每个排列都是一个数组;返回 self。排列的顺序是不确定的。

如果给出了一个正整数参数 size,则使用 self 元素的每个 size 元组重复排列调用该块。排列的数量是 self.size**size

示例

  • size 为 1

    p = []
    [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
    p # => [[0], [1], [2]]
    
  • size 为 2

    p = []
    [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
    p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
    

如果 size 为零,则使用一个空数组调用该块一次。

如果 size 为负数,则不调用该块。

[0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }

如果没有给定代码块,则返回一个新的 Enumerator

相关:请参阅 组合方法

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_array) → self

self 的元素替换为 other_array 的元素,other_array 必须是 可转换为数组的对象;返回 self

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

相关:请参阅 赋值方法

别名为:initialize_copy
reverse → new_array 点击切换源代码

返回一个新数组,其中包含 self 的元素,顺序相反。

[0, 1, 2].reverse # => [2, 1, 0]

相关:请参阅 组合方法

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! → self 点击切换源代码

反转 self 元素的顺序;返回 self

a = [0, 1, 2]
a.reverse! # => [2, 1, 0]
a          # => [2, 1, 0]

相关:请参阅 赋值方法

static VALUE
rb_ary_reverse_bang(VALUE ary)
{
    return rb_ary_reverse(ary);
}
reverse_each {|element| ... } → self 点击切换源代码
reverse_each → Enumerator

当给出一个块时,以相反的顺序遍历 self 的元素,并将每个元素按相反的顺序传递给该块;返回 self

a = []
[0, 1, 2].reverse_each {|element| a.push(element) }
a # => [2, 1, 0]

允许在迭代期间修改数组。

a = ['a', 'b', 'c']
a.reverse_each {|element| a.clear if element.start_with?('b') }
a # => []

当没有给出块时,返回一个新的 Enumerator

相关信息:请参阅 用于迭代的方法

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(object) → integer or nil 点击切换源代码
rindex {|element| ... } → integer or nil
rindex → new_enumerator

返回 object == element 的最后一个元素的索引。

如果给出了参数 object,则返回找到的最后一个此类元素的索引。

a = [:foo, 'bar', 2, 'bar']
a.rindex('bar') # => 3

如果未找到此类对象,则返回 nil

如果给出了块,则使用每个连续的元素调用该块;返回该块返回真值的最后一个元素的索引。

a = [:foo, 'bar', 2, 'bar']
a.rindex {|element| element == 'bar' } # => 3

如果代码块从未返回真值,则返回 nil

当既没有给出参数也没有给出块时,返回一个新的 Enumerator

相关信息:请参阅 用于查询的方法

static VALUE
rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
{
    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");
    while (i--) {
        VALUE e = RARRAY_AREF(ary, i);
        if (rb_equal(e, val)) {
            return LONG2NUM(i);
        }
        if (i > RARRAY_LEN(ary)) {
            break;
        }
    }
    return Qnil;
}
rotate(count = 1) → new_array 点击切换源代码

返回一个由 self 形成的新的数组,其中的元素从一端旋转到另一端。

对于非负数值 count,将元素从开头旋转到结尾。

[0, 1, 2, 3].rotate(2)   # => [2, 3, 0, 1]
[0, 1, 2, 3].rotate(2.1) # => [2, 3, 0, 1]

如果 count 很大,则使用 count % array.size 作为计数。

[0, 1, 2, 3].rotate(22) # => [2, 3, 0, 1]

如果 count 为零,则不旋转任何元素。

[0, 1, 2, 3].rotate(0) # => [0, 1, 2, 3]

对于负数值 count,从结尾到开头按相反方向旋转。

[0, 1, 2, 3].rotate(-1) # => [3, 0, 1, 2]

如果 count 很小(远离零),则使用 count % array.size 作为计数。

[0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]

相关:请参阅 获取方法

static VALUE
rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE rotated;
    const VALUE *ptr;
    long len;
    long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);

    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) → self 点击切换源代码

通过将元素从一端移动到另一端来就地旋转 self;返回 self

对于非负数值 count,将 count 个元素从开头旋转到结尾。

[0, 1, 2, 3].rotate!(2)   # => [2, 3, 0, 1]
[0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]

如果 count 很大,则使用 count % array.size 作为计数。

[0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]

如果 count 为零,则不旋转任何元素。

[0, 1, 2, 3].rotate!(0) # => [0, 1, 2, 3]

对于负数值 count,从结尾到开头按相反方向旋转。

[0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]

如果 count 很小(远离零),则使用 count % array.size 作为计数。

[0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]

相关:请参阅 赋值方法

static VALUE
rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
{
    long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
    rb_ary_rotate(ary, n);
    return ary;
}
sample(random: Random) → object 点击切换源代码
sample(count, random: Random) → new_ary

返回 self 中的随机元素,由关键字参数 random 给出的对象选择。

如果没有给出参数 count,则返回 self 中的一个随机元素。

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

如果 self 为空,则返回 nil

[].sample # => nil

如果给出了非负数值参数 count,则返回一个新数组,其中包含 self 中的 count 个随机元素。

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

结果数组的顺序与 self 的顺序无关。

如果 self 为空,则返回一个新的空 Array

[].sample(4) # => []

可能会在 self 中返回重复项。

a = [1, 1, 1, 2, 2, 3]
a.sample(a.size) # => [1, 1, 3, 2, 1, 2]

返回的元素不超过 a.size 个(因为没有引入新的重复项)。

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

使用关键字参数 random 给出的对象作为随机数生成器。

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

相关:请参阅 获取方法

# File ruby_3_4_1/array.rb, line 95
def sample(n = (ary = false), random: Random)
  if Primitive.mandatory_only?
    # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
    Primitive.ary_sample0
  else
    # Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) }
    Primitive.ary_sample(random, n, ary)
  end
end
select {|element| ... } → new_array 点击切换源代码
select → new_enumerator

如果给定了代码块,则对 self 的每个元素调用该代码块;返回一个新数组,其中包含 self 中代码块返回真值的那些元素。

a = [:foo, 'bar', 2, :bam]
a.select {|element| element.to_s.start_with?('b') }
# => ["bar", :bam]

如果没有给定代码块,则返回一个新的 Enumerator

相关:请参阅 获取方法

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;
}
别名为:filter, filter
select! {|element| ... } → self or nil 点击切换源代码
select! → new_enumerator

如果给定了代码块,则对 self 的每个元素调用该代码块;从 self 中删除代码块返回 falsenil 的那些元素。

如果删除了任何元素,则返回 self

a = [:foo, 'bar', 2, :bam]
a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]

如果未删除任何元素,则返回 nil

如果没有给定代码块,则返回一个新的 Enumerator

相关信息:请参阅 用于删除的方法

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);
}
别名为:filter!
shift → object or nil 点击切换源代码
shift(count) → new_array or nil

self 中删除并返回前导元素。

如果没有参数,则删除并返回一个元素(如果有),否则返回 nil

a = [0, 1, 2, 3]
a.shift  # => 0
a        # => [1, 2, 3]
[].shift # => nil

如果给出了非负数值参数 count,则删除并返回前 count 个元素。

a = [0, 1, 2, 3]
a.shift(2)   # => [0, 1]
a            # => [2, 3]
a.shift(1.1) # => [2]
a            # => [3]
a.shift(0)   # => []
a            # => [3]

如果 count 很大,则删除并返回所有元素。

a = [0, 1, 2, 3]
a.shift(50) # => [0, 1, 2, 3]
a           # => []

如果 self 为空,则返回一个新的空数组。

相关信息:请参阅 用于删除的方法

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);
    rb_ary_behead(ary,n);

    return result;
}
shuffle(random: Random) → new_array 点击切换源代码

返回一个新数组,其中包含 self 中的所有元素,顺序随机,由关键字参数 random 给出的对象选择。

a =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3]

包含重复元素。

a =            [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]

使用关键字参数 random 给出的对象作为随机数生成器。

相关:请参阅 获取方法

# File ruby_3_4_1/array.rb, line 45
def shuffle(random: Random)
  Primitive.rb_ary_shuffle(random)
end
shuffle!(random: Random) → self 点击切换源代码

self 中的所有元素随机打乱,由关键字参数 random 给出的对象选择。返回 self

a =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]

包含重复元素。

a =             [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]

使用关键字参数 random 给出的对象作为随机数生成器。

相关:请参阅 赋值方法

# File ruby_3_4_1/array.rb, line 22
def shuffle!(random: Random)
  Primitive.rb_ary_shuffle_bang(random)
end
size → integer

返回 self 中元素的计数

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

相关信息:请参阅 用于查询的方法

别名为:length
slice(index) → object or nil
slice(start, length) → object or nil
slice(range) → object or nil
slice(aseq) → object or nil

self 返回元素;不修改 self

简而言之

a = [:foo, 'bar', 2]

# Single argument index: returns one element.
a[0]     # => :foo          # Zero-based index.
a[-1]    # => 2             # Negative index counts backwards from end.

# Arguments start and length: returns an array.
a[1, 2]  # => ["bar", 2]
a[-2, 2] # => ["bar", 2]    # Negative start counts backwards from end.

# Single argument range: returns an array.
a[0..1]  # => [:foo, "bar"]
a[0..-2] # => [:foo, "bar"] # Negative range-begin counts backwards from end.
a[-2..2] # => ["bar", 2]    # Negative range-end counts backwards from end.

当给定单个整数参数 index 时,返回偏移量 index 处的元素

a = [:foo, 'bar', 2]
a[0] # => :foo
a[2] # => 2
a # => [:foo, "bar", 2]

如果 index 为负,则从 self 的末尾向后计数

a = [:foo, 'bar', 2]
a[-1] # => 2
a[-2] # => "bar"

如果 index 超出范围,则返回 nil

当给定两个 Integer 参数 startlength 时,返回一个大小为 length 的新 Array,其中包含从偏移量 start 开始的连续元素

a = [:foo, 'bar', 2]
a[0, 2] # => [:foo, "bar"]
a[1, 2] # => ["bar", 2]

如果 start + length 大于 self.length,则返回从偏移量 start 到末尾的所有元素

a = [:foo, 'bar', 2]
a[0, 4] # => [:foo, "bar", 2]
a[1, 3] # => ["bar", 2]
a[2, 2] # => [2]

如果 start == self.sizelength >= 0,则返回一个新的空 Array

如果 length 为负数,则返回 nil

当给定单个 Range 参数 range 时,将 range.min 视为上面的 start,将 range.size 视为上面的 length

a = [:foo, 'bar', 2]
a[0..1] # => [:foo, "bar"]
a[1..2] # => ["bar", 2]

特殊情况:如果 range.start == a.size,则返回一个新的空 Array

如果 range.end 为负,则从末尾计算结束索引

a = [:foo, 'bar', 2]
a[0..-1] # => [:foo, "bar", 2]
a[0..-2] # => [:foo, "bar"]
a[0..-3] # => [:foo]

如果 range.start 为负,则从末尾计算起始索引

a = [:foo, 'bar', 2]
a[-1..2] # => [2]
a[-2..2] # => ["bar", 2]
a[-3..2] # => [:foo, "bar", 2]

如果 range.start 大于数组大小,则返回 nil

a = [:foo, 'bar', 2]
a[4..1] # => nil
a[4..0] # => nil
a[4..-1] # => nil

当给定单个 Enumerator::ArithmeticSequence 参数 aseq 时,返回一个与序列生成的索引相对应的元素 Array

a = ['--', 'data1', '--', 'data2', '--', 'data3']
a[(1..).step(2)] # => ["data1", "data2", "data3"]

与使用范围切片不同,如果算术序列的开头或结尾大于数组大小,则抛出 RangeError

a = ['--', 'data1', '--', 'data2', '--', 'data3']
a[(1..11).step(2)]
# RangeError (((1..11).step(2)) out of range)
a[(7..).step(2)]
# RangeError (((7..).step(2)) out of range)

如果给定的参数是单个参数,并且其类型不是列出的类型之一,则尝试将其转换为 Integer,如果无法转换,则引发错误

a = [:foo, 'bar', 2]
# Raises TypeError (no implicit conversion of Symbol into Integer):
a[:foo]

相关:请参阅 获取方法

别名为:[]
slice!(index) → object or nil 点击切换源代码
slice!(start, length) → new_array or nil
slice!(range) → new_array or nil

self 中删除并返回元素。

如果给出了数值参数 index,则删除并返回偏移量 index 处的元素。

a = ['a', 'b', 'c', 'd']
a.slice!(2)   # => "c"
a             # => ["a", "b", "d"]
a.slice!(2.1) # => "d"
a             # => ["a", "b"]

如果 index 为负,则从 self 的末尾向后计数

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

如果 index 超出范围,则返回 nil

如果给出了数值参数 startlength,则从零开始的偏移量 start 开始删除 self 中的 length 个元素;在新数组中返回已删除的对象。

a = ['a', 'b', 'c', 'd']
a.slice!(1, 2)     # => ["b", "c"]
a                  # => ["a", "d"]
a.slice!(0.1, 1.1) # => ["a"]
a                  # => ["d"]

如果 start 为负数,则从 self 的末尾向后计数。

a = ['a', 'b', 'c', 'd']
a.slice!(-2, 1) # => ["c"]
a               # => ["a", "b", "d"]

如果 start 超出范围,则返回 nil

a = ['a', 'b', 'c', 'd']
a.slice!(5, 1)  # => nil
a.slice!(-5, 1) # => nil

如果 start + length 超过数组大小,则删除并返回从偏移量 start 到末尾的所有元素。

a = ['a', 'b', 'c', 'd']
a.slice!(2, 50) # => ["c", "d"]
a               # => ["a", "b"]

如果 start == a.size 并且 length 为非负数,则返回一个新的空数组。

如果 length 为负数,则返回 nil

如果给出了 Range 参数 range,则将 range.min 视为 start(如上),将 range.size 视为 length(如上)。

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

如果 range.start == a.size,则返回一个新的空数组。

a = ['a', 'b', 'c', 'd']
a.slice!(4..5) # => []

如果 range.start 大于数组大小,则返回 nil

a = ['a', 'b', 'c', 'd']
a.slice!(5..6) # => nil

如果 range.start 为负数,则通过从 self 的末尾向后计数来计算起始索引。

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

如果 range.end 为负数,则通过从 self 的末尾向后计数来计算结束索引。

a = ['a', 'b', 'c', 'd']
a.slice!(0..-2) # => ["a", "b", "c"]

相关信息:请参阅 用于删除的方法

static VALUE
rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg1;
    long pos, len;

    rb_ary_modify_check(ary);
    rb_check_arity(argc, 1, 2);
    arg1 = argv[0];

    if (argc == 2) {
        pos = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
    }

    if (!FIXNUM_P(arg1)) {
        switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
          case Qtrue:
            /* valid range */
            return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
          case Qnil:
            /* invalid range */
            return Qnil;
          default:
            /* not a range */
            break;
        }
    }

    return rb_ary_delete_at(ary, NUM2LONG(arg1));
}
sort → new_array 点击切换源代码
sort {|a, b| ... } → new_array

返回一个新数组,其中包含 self 的元素,并已排序。

如果没有给出块,则使用运算符 #<=> 比较元素(请参阅 Object#<=>)。

[0, 2, 3, 1].sort # => [0, 1, 2, 3]

如果给出了块,则使用 self 中的每对元素组合调用该块;对于每一对 ab,该块应返回一个数值。

  • ba 之后时,返回负数。

  • ab 等效时,返回零。

  • ab 之后时,返回正数。

示例

a = [3, 2, 0, 1]
a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]

当该块返回零时,ab 的顺序是不确定的,并且可能不稳定。

相关:请参阅 获取方法

VALUE
rb_ary_sort(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_sort_bang(ary);
    return ary;
}
sort! → self 点击切换源代码
sort! {|a, b| ... } → self

类似于 Array#sort,但返回 self,其元素就地排序。

相关:请参阅 赋值方法

VALUE
rb_ary_sort_bang(VALUE ary)
{
    rb_ary_modify(ary);
    RUBY_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.receiver = ary;
        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);
            }
            if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
                ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
            }
            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 {
                RUBY_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 {
                    ary_heap_free(ary);
                }
                ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
                ARY_SET_HEAP_LEN(ary, len);
                ARY_SET_CAPA(ary, ARY_HEAP_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 */
    }
    ary_verify(ary);
    return ary;
}
sort_by! {|element| ... } → self 点击以切换源代码
sort_by! → new_enumerator

如果给定了代码块,则对 self 的元素进行原地排序;返回 self。

使用每个连续的元素调用代码块;根据代码块返回的值对元素进行排序。

a = ['aaaa', 'bbb', 'cc', 'd']
a.sort_by! {|element| element.size }
a # => ["d", "cc", "bbb", "aaaa"]

对于代码块返回的重复值,排序是不确定的,并且可能是不稳定的。

如果没有给定代码块,则返回一个新的 Enumerator

相关:请参阅 赋值方法

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) → object 点击以切换源代码
sum(init = 0) {|element| ... } → object

如果没有给出代码块,则返回 initself 所有元素的总和;对于数组 array 和值 init,等效于

sum = init
array.each {|element| sum += element }
sum

例如,[e0, e1, e2].sum 返回 init + e0 + e1 + e2

示例

[0, 1, 2, 3].sum                 # => 6
[0, 1, 2, 3].sum(100)            # => 106
['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
[[:foo, :bar], ['foo', 'bar']].sum([2, 3])
# => [2, 3, :foo, :bar, "foo", "bar"]

init 值和元素不需要是数字,但必须都与 + 兼容。

# Raises TypeError: Array can't be coerced into Integer.
[[:foo, :bar], ['foo', 'bar']].sum(2)

如果给定了代码块,则使用 self 的每个元素调用代码块;代码块的返回值(而不是元素本身)被用作加数。

['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
# => "Coerced and concatenated: zero1two"

注意

static VALUE
rb_ary_sum(int argc, VALUE *argv, VALUE ary)
{
    VALUE e, v, r;
    long i, n;
    int block_given;

    v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));

    block_given = rb_block_given_p();

    if (RARRAY_LEN(ary) == 0)
        return v;

    n = 0;
    r = Qundef;

    if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
        i = 0;
        goto init_is_a_value;
    }

    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_BIGNUM_TYPE_P(e))
            v = rb_big_plus(e, v);
        else if (RB_TYPE_P(e, T_RATIONAL)) {
            if (UNDEF_P(r))
                r = e;
            else
                r = rb_rational_plus(r, e);
        }
        else
            goto not_exact;
    }
    v = finish_exact_sum(n, r, v, argc!=0);
    return v;

  not_exact:
    v = finish_exact_sum(n, r, v, i!=0);

    if (RB_FLOAT_TYPE_P(e)) {
        /*
         * Kahan-Babuska balancing compensated summation algorithm
         * See https://link.springer.com/article/10.1007/s00607-005-0139-x
         */
        double f, c;
        double x, t;

        f = NUM2DBL(v);
        c = 0.0;
        goto has_float_value;
        for (; i < RARRAY_LEN(ary); i++) {
            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_BIGNUM_TYPE_P(e))
                x = rb_big2dbl(e);
            else if (RB_TYPE_P(e, T_RATIONAL))
                x = rb_num2dbl(e);
            else
                goto not_float;

            if (isnan(f)) continue;
            if (isnan(x)) {
                f = x;
                continue;
            }
            if (isinf(x)) {
                if (isinf(f) && signbit(x) != signbit(f))
                    f = NAN;
                else
                    f = x;
                continue;
            }
            if (isinf(f)) continue;

            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;
    init_is_a_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(count) → new_array 点击以切换源代码

返回一个新数组,其中包含 self 的前 count 个元素(如果可用);count 必须是非负数;不会修改 self

a = ['a', 'b', 'c', 'd']
a.take(2)   # => ["a", "b"]
a.take(2.1) # => ["a", "b"]
a.take(50)  # => ["a", "b", "c", "d"]
a.take(0)   # => []

相关:请参阅 获取方法

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 {|element| ... } → new_array 点击以切换源代码
take_while → new_enumerator

如果给定了代码块,则使用 self 的每个连续元素调用代码块;如果代码块返回 falsenil,则停止迭代;返回一个新数组,其中包含那些代码块返回真值的元素。

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

如果没有给定代码块,则返回一个新的 Enumerator

不修改 self

相关:请参阅 获取方法

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 → self 或 new_array 点击以切换源代码

selfArray 的实例时,返回 self

否则,返回一个包含 self 元素的新数组。

class MyArray < Array; end
my_a = MyArray.new(['foo', 'bar', 'two'])
a = my_a.to_a
a # => ["foo", "bar", "two"]
a.class # => Array # Not MyArray.

相关:请参阅 用于转换的方法

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 → self 点击以切换源代码

返回 self

static VALUE
rb_ary_to_ary_m(VALUE ary)
{
    return ary;
}
to_h → new_hash 点击以切换源代码
to_h {|element| ... } → new_hash

返回由 self 形成的新哈希。

如果没有给出代码块,则 self 的每个元素必须是包含 2 个元素的子数组;将每个子数组在新哈希中形成键值对。

a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
[].to_h # => {}

如果给出了代码块,则代码块必须返回一个包含 2 个元素的数组;使用 self 的每个元素调用代码块;将每个返回的数组在返回的哈希中形成键值对。

a = ['foo', :bar, 1, [2, 3], {baz: 4}]
a.to_h {|element| [element, element.class] }
# => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}

相关:请参阅 用于转换的方法

static VALUE
rb_ary_to_h(VALUE ary)
{
    long i;
    VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
    int block_given = rb_block_given_p();

    for (i=0; i<RARRAY_LEN(ary); i++) {
        const VALUE e = rb_ary_elt(ary, i);
        const VALUE elt = block_given ? rb_yield_force_blockarg(e) : e;
        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 → new_string

返回通过对每个数组元素调用方法 #inspect 形成的新字符串

a = [:foo, 'bar', 2]
a.inspect # => "[:foo, \"bar\", 2]"

相关:请参阅 用于转换的方法

别名: inspect
transpose → new_array 点击以切换源代码

返回一个新数组,它是 self转置矩阵

a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]

self 的元素必须全部大小相同。

相关:请参阅 用于转换的方法

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;
}
union(*other_arrays) → new_array 点击以切换源代码

返回一个新数组,它是 self 和所有给定数组 other_arrays 的元素的并集;使用 eql? 比较项。

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

删除重复项(保留第一个找到的项)。

[0, 1, 1].union([2, 1], [3, 1]) # => [0, 1, 2, 3]

保留顺序(保留第一个找到的项的位置)。

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

如果没有给出参数,则返回 self 的副本。

相关:请参阅 组合方法

static VALUE
rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
{
    int i;
    long sum;
    VALUE hash;

    sum = RARRAY_LEN(ary);
    for (i = 0; i < argc; i++) {
        argv[i] = to_ary(argv[i]);
        sum += RARRAY_LEN(argv[i]);
    }

    if (sum <= SMALL_ARRAY_LEN) {
        VALUE ary_union = rb_ary_new();

        rb_ary_union(ary_union, ary);
        for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);

        return ary_union;
    }

    hash = ary_make_hash(ary);
    for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);

    return rb_hash_values(hash);
}
uniq → new_array 点击以切换源代码
uniq {|element| ... } → new_array

返回一个新数组,其中包含 self 中不重复的元素,始终保留第一个出现的元素。

如果没有给出代码块,则使用方法 eql? 比较元素,识别并忽略重复的元素。

a = [0, 0, 1, 1, 2, 2]
a.uniq # => [0, 1, 2]

如果给出了代码块,则为每个元素调用代码块;使用方法 eql? 比较代码块返回值来识别和忽略“重复”元素;也就是说,如果一个元素的代码块返回值与前一个元素的代码块返回值相同,则该元素是重复的。

a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
a.uniq {|element| element.size } # => ["a", "aa", "aaa"]

相关:用于获取的方法

static VALUE
rb_ary_uniq(VALUE ary)
{
    VALUE hash, uniq;

    if (RARRAY_LEN(ary) <= 1) {
        hash = 0;
        uniq = rb_ary_dup(ary);
    }
    else 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);
    }

    return uniq;
}
uniq! → self 或 nil 点击以切换源代码
uniq! {|element| ... } → self 或 nil

self 中删除重复的元素,始终保留第一次出现的元素;如果删除了任何元素,则返回 self,否则返回 nil

如果没有给出代码块,则使用方法 eql? 比较元素,识别并删除元素。

a = [0, 0, 1, 1, 2, 2]
a.uniq! # => [0, 1, 2]
a.uniq! # => nil

如果给出了代码块,则为每个元素调用代码块;使用方法 eql? 比较代码块返回值来识别和忽略“重复”元素;也就是说,如果一个元素的代码块返回值与前一个元素的代码块返回值相同,则该元素是重复的。

a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
a.uniq! {|element| element.size } # => nil

相关信息:请参阅 用于删除的方法

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)) {
        rb_ary_unshare(ary);
        FL_SET_EMBED(ary);
    }
    ary_resize_capa(ary, hash_size);
    rb_hash_foreach(hash, push_value, ary);

    return ary;
}
unshift(*objects) → self 点击以切换源代码

将给定的 objects 添加到 self 的开头

a = [:foo, 'bar', 2]
a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]

相关:Array#shift;另请参阅 用于赋值的方法

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;
}
别名: prepend
values_at(*specifiers) → new_array 点击以切换源代码

在新数组中返回 self 中的元素;不会修改 self

返回的数组中包含的对象是 self 中由给定的 specifiers 选择的元素,其中每个 specifiers 必须是数值索引或 Range

简而言之

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

# Index specifiers.
a.values_at(2, 0, 2, 0)     # => ["c", "a", "c", "a"] # May repeat.
a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
a.values_at(-50, 50)        # => [nil, nil]           # Outside of self.

# Range specifiers.
a.values_at(1..3)       # => ["b", "c", "d"] # From range.begin to range.end.
a.values_at(1...3)      # => ["b", "c"]      # End excluded.
a.values_at(3..1)       # => []              # No such elements.

a.values_at(-3..3)  # => ["b", "c", "d"]     # Negative range.begin counts backwards.
a.values_at(-50..3)                          # Raises RangeError.

a.values_at(1..-2)  # => ["b", "c"]          # Negative range.end counts backwards.
a.values_at(1..-50) # => []                  # No such elements.

# Mixture of specifiers.
a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]

如果没有给出 specifiers,则返回一个新的空数组。

a = ['a', 'b', 'c', 'd']
a.values_at # => []

对于每个数值 index,包含一个元素。

  • 对于每个范围内的非负数值 index(小于 self.size),包含偏移量为 index 的元素。

    a.values_at(0, 2)     # => ["a", "c"]
    a.values_at(0.1, 2.9) # => ["a", "c"]
    
  • 对于每个范围内的负数值 index(大于或等于 - self.size),从 self 的末尾向后计数。

    a.values_at(-1, -4) # => ["d", "a"]
    

给定的索引可以按任意顺序排列,并且可以重复。

a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]

对于每个超出范围的 index,包含 nil

a.values_at(4, -5) # => [nil, nil]

对于每个 Range 指定符 range,根据 range.beginrange.end 包含元素。

  • 如果 range.beginrange.end 都是非负数并且在范围内(小于 self.size),则包含从索引 range.beginrange.end - 1 (如果 range.exclude_end? 为真),或到 range.end (否则) 的元素。

    a.values_at(1..2)  # => ["b", "c"]
    a.values_at(1...2) # => ["b"]
    
  • 如果 range.begin 是负数且在范围内(大于或等于 - self.size),则从 self 的末尾向后计数。

    a.values_at(-2..3) # => ["c", "d"]
    
  • 如果 range.begin 是负数且超出范围,则引发异常。

    a.values_at(-5..3) # Raises RangeError.
    
  • 如果 range.end 是正数且超出范围,则使用 nil 元素扩展返回的数组。

    a.values_at(1..5) # => ["b", "c", "d", nil, nil]
    
  • 如果 range.end 是负数且在范围内,则从 self 的末尾向后计数。

    a.values_at(1..-2) # => ["b", "c"]
    
  • 如果 range.end 是负数且超出范围,则返回空数组。

    a.values_at(1..-5) # => []
    

给定的范围可以按任意顺序排列,并且可以重复。

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

给定的指定符可以是索引和范围的任意混合。

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

相关:请参阅 获取方法

static VALUE
rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
{
    long i, olen = RARRAY_LEN(ary);
    VALUE result = rb_ary_new_capa(argc);
    for (i = 0; i < argc; ++i) {
        append_values_at_single(result, ary, olen, argv[i]);
    }
    RB_GC_GUARD(ary);
    return result;
}
zip(*other_arrays) → new_array 点击以切换源代码
zip(*other_arrays) {|sub_array| ... } → nil

如果没有给出代码块,则将 selfother_arrays 的集合组合;返回一个由子数组组成的新数组。

[0, 1].zip(['zero', 'one'], [:zero, :one])
# => [[0, "zero", :zero], [1, "one", :one]]

返回的

  • 外部数组的大小为 self.size

  • 每个子数组的大小为 other_arrays.size + 1

  • n 个子数组包含 (按顺序)

    • self 的第 n 个元素。

    • 每个其他数组的第 n 个元素(如果可用)。

示例

a = [0, 1]
zipped = a.zip(['zero', 'one'], [:zero, :one])
# => [[0, "zero", :zero], [1, "one", :one]]
zipped.size       # => 2 # Same size as a.
zipped.first.size # => 3 # Size of other arrays plus 1.

当其他数组都与 self 的大小相同时,返回的子数组是重新排列,其中包含所有数组(包括 self)的元素,没有遗漏或添加。

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3]
c = [:c0, :c1, :c2, :c3]
d = a.zip(b, c)
pp d
# =>
[[:a0, :b0, :c0],
 [:a1, :b1, :c1],
 [:a2, :b2, :c2],
 [:a3, :b3, :c3]]

当其他数组之一比 self 小时,用 nil 元素填充相应的子数组。

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2]
c = [:c0, :c1]
d = a.zip(b, c)
pp d
# =>
[[:a0, :b0, :c0],
 [:a1, :b1, :c1],
 [:a2, :b2, nil],
 [:a3, nil, nil]]

当其他数组之一比 self 大时,忽略其尾随元素。

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3, :b4]
c = [:c0, :c1, :c2, :c3, :c4, :c5]
d = a.zip(b, c)
pp d
# =>
[[:a0, :b0, :c0],
 [:a1, :b1, :c1],
 [:a2, :b2, :c2],
 [:a3, :b3, :c3]]

如果给出了代码块,则使用每个其他数组调用该代码块;返回 nil

d = []
a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3]
c = [:c0, :c1, :c2, :c3]
a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
pp d
# =>
[[:c0, :b0, :a0],
 [:c1, :b1, :a1],
 [:c2, :b2, :a2],
 [:c3, :b3, :a3]]

对于 other_arrays 中实际上不是数组的对象,如果定义了,则将“其他数组”形成为 object.to_ary,否则形成为 object.each.to_a

相关:请参阅 用于转换的方法

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;
}
self | other_array → new_array 点击以切换源代码

返回 selfother_array 的并集;删除重复项;保留顺序;使用 eql? 比较项。

[0, 1] | [2, 3] # => [0, 1, 2, 3]
[0, 1, 1] | [2, 2, 3] # => [0, 1, 2, 3]
[0, 1, 2] | [3, 2, 1, 0] # => [0, 1, 2, 3]

相关:请参阅 组合方法

static VALUE
rb_ary_or(VALUE ary1, VALUE ary2)
{
    VALUE hash;

    ary2 = to_ary(ary2);
    if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
        VALUE ary3 = rb_ary_new();
        rb_ary_union(ary3, ary1);
        rb_ary_union(ary3, ary2);
        return ary3;
    }

    hash = ary_make_hash(ary1);
    rb_ary_union_hash(hash, ary2);

    return rb_hash_values(hash);
}