Spec-Zone.ru › Ruby 2.2

класс Array

Родитель:
Объект
Включенные модули:
Enumerable

Массивы — это упорядоченные коллекции объектов с целочисленными индексами.

Индексация массива начинается с 0, как в C или Java. Отрицательный индекс предполагается относительным к концу массива — то есть индекс -1 указывает на последний элемент массива, -2 — на предпоследний и так далее.

Создание массивов

Новый массив можно создать, используя литеральный конструктор []. Массивы могут содержать различные типы объектов. Например, массив ниже содержит целое число, строку и число с плавающей точкой:

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

Массив также можно создать, явно вызвав ::new с нулём, одним (начальный размер массива) или двумя аргументами (начальный размер и значение по умолчанию).

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

Обратите внимание, что второй аргумент заполняет массив ссылками на тот же объект. Поэтому рекомендуется использовать только в случаях, когда вам нужно инициализировать массивы с неизменяемыми объектами, такими как символы, числа, true или false.

Чтобы создать массив с отдельными объектами, можно передать блок вместо этого. Этот метод безопасно использовать с изменяемыми объектами, такими как хэши, строки или другие массивы:

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

Это также быстрый способ построения многомерных массивов:

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

Массив также можно создать, используя метод Array(), предоставляемый Kernel, который пытается вызвать to_ary, а затем to_a над своим аргументом.

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

Пример использования

Помимо методов, которые он наследует через модуль Enumerable, класс Array имеет собственные методы для доступа, поиска и других манипуляций с массивами.

Некоторые из наиболее распространённых из них проиллюстрированы ниже.

Доступ к элементам

Элементы массива можно получить, используя метод #[]. Он может принимать один целочисленный аргумент (числовой индекс), пару аргументов (начало и длина) или диапазон. Отрицательные индексы начинают отсчёт с конца, где -1 — последний элемент.

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

Ещё один способ доступа к конкретному элементу массива — использование метода at

arr.at(0) #=> 1

Метод slice работает аналогично #[].

Чтобы вызвать ошибку для индексов за пределами границ массива или предоставить значение по умолчанию, когда это произойдёт, вы можете использовать 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"

Специальные методы first и last возвращают первый и последний элементы массива соответственно.

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

Чтобы вернуть первые n элементов массива, используйте take

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

drop делает обратное take, возвращая элементы после того, как n элементов были удалены:

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

Получение информации о массиве

Массивы отслеживают свою длину постоянно. Чтобы узнать количество элементов в массиве, используйте length, count или size.

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

Чтобы проверить, содержит ли массив какие-либо элементы вообще

browsers.empty? #=> false

Чтобы проверить, включён ли определённый элемент в массив

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

Добавление элементов в массивы

Элементы можно добавлять в конец массива, используя либо push, либо <<

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

unshift добавит новый элемент в начало массива.

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

С помощью 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]

Удаление элементов из массива

Метод 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, массив имеет метод each, который определяет, какие элементы должны быть проитерированы и как. В случае each массива все элементы экземпляра массива передаются в предоставленный блок последовательно.

Обратите внимание, что эта операция не изменяет массив.

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

Ещё один иногда полезный итератор — reverse_each, который итерирует элементы массива в обратном порядке.

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

Метод map может использоваться для создания нового массива на основе исходного массива, но со значениями, изменёнными предоставленным блоком:

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

Выбор элементов из массива

Элементы массива можно выбирать в соответствии с критериями, определёнными в блоке. Выбор может происходить разрушающим или неразрушающим способом. В то время как разрушающие операции изменят массив, над которым они вызваны, неразрушающие методы обычно возвращают новый массив с выбранными элементами, но оставляют исходный массив неизменным.

Неразрушающий выбор

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

Разрушающий выбор

select! и reject! — соответствующие разрушающие методы для select и reject

Аналогично select против reject, delete_if и keep_if дают совершенно противоположный результат при использовании одного и того же блока:

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

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

Общедоступные методы класса

[](*args) Показать исходный код
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;
}

Возвращает новый массив, заполненный указанными объектами.

Array.[]( 1, 'a', /^A/ ) # => [1, "a", /^A/]
Array[ 1, 'a', /^A/ ]    # => [1, "a", /^A/]
[ 1, 'a', /^A/ ]         # => [1, "a", /^A/]
new(size=0, default=nil) Показать исходный код
new(array)
new(size) {|index| block }
static VALUE
rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
{
    long len;
    VALUE size, val;

    rb_ary_modify(ary);
    if (argc == 0) {
        if (ARY_OWNS_HEAP_P(ary) && RARRAY_CONST_PTR(ary) != 0) {
            ruby_sized_xfree((void *)RARRAY_CONST_PTR(ary), ARY_HEAP_SIZE(ary));
        }
        rb_ary_unshare_safe(ary);
        FL_SET_EMBED(ary);
        ARY_SET_EMBED_LEN(ary, 0);
        if (rb_block_given_p()) {
            rb_warning("given block not used");
        }
        return ary;
    }
    rb_scan_args(argc, argv, "02", &size, &val);
    if (argc == 1 && !FIXNUM_P(size)) {
        val = rb_check_array_type(size);
        if (!NIL_P(val)) {
            rb_ary_replace(ary, val);
            return ary;
        }
    }

    len = NUM2LONG(size);
    /* NUM2LONG() may call size.to_int, ary can be frozen, modified, etc */
    if (len < 0) {
        rb_raise(rb_eArgError, "negative array size");
    }
    if (len > ARY_MAX_SIZE) {
        rb_raise(rb_eArgError, "array size too big");
    }
    /* recheck after argument conversion */
    rb_ary_modify(ary);
    ary_resize_capa(ary, len);
    if (rb_block_given_p()) {
        long i;

        if (argc == 2) {
            rb_warn("block supersedes default value argument");
        }
        for (i=0; i<len; i++) {
            rb_ary_store(ary, i, rb_yield(LONG2NUM(i)));
            ARY_SET_LEN(ary, i + 1);
        }
    }
    else {
        ary_memfill(ary, 0, len, val);
        ARY_SET_LEN(ary, len);
    }
    return ary;
}

Возвращает новый массив.

В первом случае, если аргументы не передаются, новый массив будет пустым. Когда передаются size и необязательный default аргументы, создаётся массив с size копиями default. Обратите внимание, что все элементы будут ссылаться на один и тот же объект default.

Второй вариант создаёт копию переданного массива (массив генерируется путём вызова #to_ary над параметром).

first_array = ["Matz", "Guido"]

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

first_array.equal? second_array       #=> false

В последнем варианте создаётся массив заданного размера. Каждый элемент в этом массиве создаётся путём передачи индекса элемента в заданный блок и сохранения возвращаемого значения.

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

Общие особенности

При передаче второго параметра, один и тот же объект будет использоваться как значение для всех элементов массива:

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

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

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

Поскольку все элементы массива хранят один и тот же хэш, изменения в одном из них будут влиять на все.

Если вам нужны отдельные копии, используйте версию с блоком, которая каждый раз использует результат этого блока для инициализации элемента массива:

a = Array.new(2) { Hash.new }
a[0]['cat'] = 'feline'
a # => [{"cat"=>"feline"}, {}]
try_convert(obj) → array or nil Показать исходный код
static VALUE
rb_ary_s_try_convert(VALUE dummy, VALUE ary)
{
    return rb_check_array_type(ary);
}

Пытается преобразовать obj в массив, используя метод to_ary. Возвращает преобразованный массив или nil, если obj не может быть преобразован по какой-либо причине. Этот метод можно использовать для проверки, является ли аргумент массивом.

Array.try_convert([1])   #=> [1]
Array.try_convert("1")   #=> nil

if tmp = Array.try_convert(arg)
  # the argument is an array
elsif tmp = String.try_convert(arg)
  # the argument is a string
end

Методы общедоступного экземпляра

ary & other_ary → new_ary Показать исходный код
static VALUE
rb_ary_and(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3, v;
    st_table *table;
    st_data_t vv;
    long i;

    ary2 = to_ary(ary2);
    ary3 = rb_ary_new();
    if (RARRAY_LEN(ary2) == 0) return ary3;
    hash = ary_make_hash(ary2);
    table = rb_hash_tbl_raw(hash);

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

    return ary3;
}

Пересечение множеств — Возвращает новый массив, содержащий элементы, общие для двух массивов, исключая дубликаты. Порядок сохраняется из исходного массива.

Для повышения эффективности сравнение элементов выполняется с использованием их методов hash и eql?.

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

См. также #uniq.

ary * int → new_ary Показать исходный код
ary * str → new_string
static VALUE
rb_ary_times(VALUE ary, VALUE times)
{
    VALUE ary2, tmp;
    const VALUE *ptr;
    long t, len;

    tmp = rb_check_string_type(times);
    if (!NIL_P(tmp)) {
        return rb_ary_join(ary, tmp);
    }

    len = NUM2LONG(times);
    if (len == 0) {
        ary2 = ary_new(rb_obj_class(ary), 0);
        goto out;
    }
    if (len < 0) {
        rb_raise(rb_eArgError, "negative argument");
    }
    if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
        rb_raise(rb_eArgError, "argument too big");
    }
    len *= RARRAY_LEN(ary);

    ary2 = ary_new(rb_obj_class(ary), len);
    ARY_SET_LEN(ary2, len);

    ptr = RARRAY_CONST_PTR(ary);
    t = RARRAY_LEN(ary);
    if (0 < t) {
        ary_memcpy(ary2, 0, t, ptr);
        while (t <= len/2) {
            ary_memcpy(ary2, t, t, RARRAY_CONST_PTR(ary2));
            t *= 2;
        }
        if (t < len) {
            ary_memcpy(ary2, t, len-t, RARRAY_CONST_PTR(ary2));
        }
    }
  out:
    OBJ_INFECT(ary2, ary);

    return ary2;
}

Повторение — При строковом аргументе эквивалентно ary.join(str).

В противном случае возвращает новый массив, составленный путём конкатенации int копий self.

[ 1, 2, 3 ] * 3    #=> [ 1, 2, 3, 1, 2, 3, 1, 2, 3 ]
[ 1, 2, 3 ] * ","  #=> "1,2,3"
ary + other_ary → new_ary Показать исходный код
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;
}

Конкатенация — Возвращает новый массив, созданный путём конкатенации двух массивов в третий.

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

Обратите внимание, что

x += y

эквивалентно

x = x + y

Это означает, что он создаёт новый массив. В результате многократное использование += для массивов может быть неэффективным.

См. также #concat.

ary - other_ary → new_ary Показать исходный код
static VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
    VALUE ary3;
    VALUE hash;
    long i;

    hash = ary_make_hash(to_ary(ary2));
    ary3 = rb_ary_new();

    for (i=0; i<RARRAY_LEN(ary1); i++) {
        if (st_lookup(rb_hash_tbl_raw(hash), RARRAY_AREF(ary1, i), 0)) continue;
        rb_ary_push(ary3, rb_ary_elt(ary1, i));
    }
    ary_recycle_hash(hash);
    return ary3;
}

Разность массивов

Возвращает новый массив, являющийся копией исходного массива, из которого удалены все элементы, также присутствующие в other_ary. Порядок сохраняется из исходного массива.

Для повышения эффективности сравнение элементов выполняется с использованием их методов hash и eql?.

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

Если вам требуется поведение, подобное множествам, используйте класс библиотеки Set.

ary << obj → ary Показать исходный код
VALUE
rb_ary_push(VALUE ary, VALUE item)
{
    long idx = RARRAY_LEN(ary);
    VALUE target_ary = ary_ensure_room_for_push(ary, 1);
    RARRAY_PTR_USE(ary, ptr, {
        RB_OBJ_WRITE(target_ary, &ptr[idx], item);
    });
    ARY_SET_LEN(ary, idx + 1);
    return ary;
}

Добавление—Добавляет заданный объект в конец этого массива. Это выражение возвращает сам массив, поэтому несколько добавлений могут быть объединены в цепочку.

[ 1, 2 ] << "c" << "d" << [ 3, 4 ]
        #=>  [ 1, 2, "c", "d", [ 3, 4 ] ]
ary <=> other_ary → -1, 0, +1 или nil Показать исходный код
VALUE
rb_ary_cmp(VALUE ary1, VALUE ary2)
{
    long len;
    VALUE v;

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

Сравнение — Возвращает целое число (-1, 0, или +1), если этот массив меньше, равен или больше other_ary.

Каждый объект в каждом массиве сравнивается (с использованием оператора <=>).

Массивы сравниваются «поэлементно»; первый элемент ary сравнивается с первым элементом other_ary с использованием оператора <=>, затем каждый из вторых элементов и т. д… Как только результат любого такого сравнения не равен нулю (т. е. два соответствующих элемента не равны), этот результат возвращается для всего сравнения массивов.

Если все элементы равны, то результат основан на сравнении длин массивов. Таким образом, два массива «равны» в соответствии с Array#<=>, если и только если они имеют одинаковую длину, а значение каждого элемента равно значению соответствующего элемента в другом массиве.

nil возвращается, если other_ary не является массивом или если сравнение двух элементов вернуло nil.

[ "a", "a", "c" ]    <=> [ "a", "b", "c" ]   #=> -1
[ 1, 2, 3, 4, 5, 6 ] <=> [ 1, 2 ]            #=> +1
[ 1, 2 ]             <=> [ 1, :two ]         #=> nil
ary == other_ary → bool Показать исходный код
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);
}

Равенство — Два массива равны, если они содержат одинаковое количество элементов и каждый элемент равен (в соответствии с Object#==) соответствующему элементу в other_ary.

[ "a", "c" ]    == [ "a", "c", 7 ]     #=> false
[ "a", "c", 7 ] == [ "a", "c", 7 ]     #=> true
[ "a", "c", 7 ] == [ "a", "d", "f" ]   #=> false
ary[index] → obj or nil Показать исходный код
ary[start, length] → new_ary or nil
ary[range] → new_ary or nil
slice(index) → obj or nil
slice(start, length) → new_ary or nil
slice(range) → new_ary or nil
VALUE
rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
    VALUE arg;
    long beg, len;

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

Ссылка на элемент — Возвращает элемент по index, или возвращает подмассив, начинающийся с start индекса и продолжающийся length элементами, или возвращает подмассив, заданный range индексов.

Отрицательные индексы отсчитываются от конца массива (–1 — это последний элемент). В start и range случаях начальный индекс находится непосредственно перед элементом. Кроме того, при пустом массиве, если начальный индекс для диапазона элементов находится в конце массива.

Возвращает nil если индекс (или начальный индекс) выходит за пределы диапазона.

a = [ "a", "b", "c", "d", "e" ]
a[2] +  a[0] + a[1]    #=> "cab"
a[6]                   #=> nil
a[1, 2]                #=> [ "b", "c" ]
a[1..3]                #=> [ "b", "c", "d" ]
a[4..7]                #=> [ "e" ]
a[6..10]               #=> nil
a[-3, 3]               #=> [ "c", "d", "e" ]
# special cases
a[5]                   #=> nil
a[6, 1]                #=> nil
a[5, 1]                #=> []
a[5..10]               #=> []
ary[index] = obj → obj Показать исходный код
ary[start, length] = obj or other_ary or nil → obj or other_ary or nil
ary[range] = obj or other_ary or nil → obj or other_ary or nil
static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
    long offset, beg, len;

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

    offset = NUM2LONG(argv[0]);
fixnum:
    rb_ary_store(ary, offset, argv[1]);
    return argv[1];
}

Присвоение элемента — Устанавливает элемент по index, или заменяет подмассив с start индекса на length элементов, или заменяет подмассив, указанный range индексов.

Если индексы превышают текущую ёмкость массива, массив автоматически увеличивается. Элементы вставляются в массив по start если length равно нулю.

Отрицательные индексы отсчитываются от конца массива. В start и range случаях начальный индекс находится непосредственно перед элементом.

Если отрицательный индекс указывает на позицию перед началом массива, возникает исключение IndexError.

См. также #push и #unshift.

a = Array.new
a[4] = "4";                 #=> [nil, nil, nil, nil, "4"]
a[0, 3] = [ 'a', 'b', 'c' ] #=> ["a", "b", "c", nil, "4"]
a[1..2] = [ 1, 2 ]          #=> ["a", 1, 2, nil, "4"]
a[0, 2] = "?"               #=> ["?", 2, nil, "4"]
a[0..2] = "A"               #=> ["A", "4"]
a[-1]   = "Z"               #=> ["A", "Z"]
a[1..-1] = nil              #=> ["A", nil]
a[1..-1] = []               #=> ["A"]
a[0, 0] = [ 1, 2 ]          #=> [1, 2, "A"]
a[3, 0] = "B"               #=> [1, 2, "A", "B"]
abbrev(pattern = nil) Показать исходный код
# File lib/abbrev.rb, line 128
def abbrev(pattern = nil)
  Abbrev::abbrev(self, pattern)
end

Вычисляет множество однозначных сокращений для строк в self.

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

Необязательный параметр pattern — это шаблон или строка. Только строки входных данных, соответствующие шаблону или начинающиеся со строки, включаются в выходной хэш.

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

Abbrev.abbrev(%w{car box cone}, "ca")
#=> {"car"=>"car", "ca"=>"car"}

См. также Abbrev#abbrev

any? [{ |obj| block }] → true or false Показать исходный код
static VALUE
rb_ary_any_p(VALUE ary)
{
    long i, len = RARRAY_LEN(ary);
    const VALUE *ptr = RARRAY_CONST_PTR(ary);

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

См. также Enumerable#any?

assoc(obj) → new_ary or nil Показать исходный код
VALUE
rb_ary_assoc(VALUE ary, VALUE key)
{
    long i;
    VALUE v;

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

Ищет в массиве, элементы которого также являются массивами, сравнивая obj с первым элементом каждого вложенного массива с использованием obj.==.

Возвращает первый вложенный массив, который соответствует (то есть первый ассоциированный массив), или nil если соответствие не найдено.

См. также #rassoc

s1 = [ "colors", "red", "blue", "green" ]
s2 = [ "letters", "a", "b", "c" ]
s3 = "foo"
a  = [ s1, s2, s3 ]
a.assoc("letters")  #=> [ "letters", "a", "b", "c" ]
a.assoc("foo")      #=> nil
at(index) → obj or nil Показать исходный код
static VALUE
rb_ary_at(VALUE ary, VALUE pos)
{
    return rb_ary_entry(ary, NUM2LONG(pos));
}

Возвращает элемент по index. Отрицательный индекс отсчитывается от конца self. Возвращает nil если индекс выходит за пределы диапазона. См. также #[].

a = [ "a", "b", "c", "d", "e" ]
a.at(0)     #=> "a"
a.at(-1)    #=> "e"
bsearch {|x| блок } → элемент Показать исходный код
static VALUE
rb_ary_bsearch(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 (FIX2INT(v) == 0) return val;
            smaller = FIX2INT(v) < 0;
        }
        else if (v == Qtrue) {
            satisfied = 1;
            smaller = 1;
        }
        else if (v == Qfalse || v == Qnil) {
            smaller = 0;
        }
        else if (rb_obj_is_kind_of(v, rb_cNumeric)) {
            const VALUE zero = INT2FIX(0);
            switch (rb_cmpint(rb_funcallv(v, id_cmp, 1, &zero), v, INT2FIX(0))) {
                case 0: return val;
                case 1: smaller = 1; break;
                case -1: smaller = 0;
            }
        }
        else {
            rb_raise(rb_eTypeError, "wrong argument type %s"
                " (must be numeric, true, false or nil)",
                rb_obj_classname(v));
        }
        if (smaller) {
            high = mid;
        }
        else {
            low = mid + 1;
        }
    }
    if (low == RARRAY_LEN(ary)) return Qnil;
    if (!satisfied) return Qnil;
    return rb_ary_entry(ary, low);
}

Используя двоичный поиск, находит значение из этого массива, которое удовлетворяет заданному условию за O(log n), где n — размер массива.

Этот метод можно использовать в двух случаях: в режиме поиска минимума и в режиме поиска любого значения. В любом случае элементы массива должны быть монотонными (или отсортированными) относительно блока.

В режиме поиска минимума (это хороший выбор для типичного случая использования) блок должен возвращать true или false, и должен существовать индекс i (0 ≤ i ≤ ary.size), такой что:

  • блок возвращает false для любого элемента, индекс которого меньше i, и

  • блок возвращает true для любого элемента, индекс которого больше или равен i.

Этот метод возвращает i-й элемент. Если i равно ary.size, он возвращает nil.

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

В режиме поиска любого значения (это поведение аналогично bsearch(3) из libc) блок должен возвращать число, и должны существовать два индекса i и j (0 ≤ i ≤ j ≤ ary.size), такие что:

  • блок возвращает положительное число для ary, если 0 < k < i,

  • блок возвращает ноль для ary, если i ≤ k < j, и

  • блок возвращает отрицательное число для ary, если j ≤ k < ary.size.

При этом методе возвращается любой элемент, индекс которого находится в пределах i…j. Если i равно j (то есть нет элемента, удовлетворяющего блоку), метод возвращает nil.

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

Нельзя смешивать оба режима одновременно; блок должен всегда возвращать либо true/false, либо всегда возвращать число. Неопределено, какое значение фактически выбирается на каждой итерации.

clear → ary Показать исходный код
VALUE
rb_ary_clear(VALUE ary)
{
    rb_ary_modify_check(ary);
    ARY_SET_LEN(ary, 0);
    if (ARY_SHARED_P(ary)) {
        if (!ARY_EMBED_P(ary)) {
            rb_ary_unshare(ary);
            FL_SET_EMBED(ary);
        }
    }
    else if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
        ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
    }
    return ary;
}

Удаляет все элементы из self.

a = [ "a", "b", "c", "d", "e" ]
a.clear    #=> [ ]
collect { |элемент| блок } → новый_массив Показать исходный код
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;
}

Вызывает заданный блок один раз для каждого элемента массива self.

Создает новый массив, содержащий значения, возвращаемые блоком.

См. также Enumerable#collect.

Если блок не задан, вместо него возвращается Перечислитель.

a = [ "a", "b", "c", "d" ]
a.collect { |x| x + "!" }        #=> ["a!", "b!", "c!", "d!"]
a.map.with_index{ |x, i| x * i } #=> ["", "b", "cc", "ddd"]
a                                #=> ["a", "b", "c", "d"]
collect! {|элемент| блок } → массив Показать исходный код
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;
}

Вызывает заданный блок один раз для каждого элемента массива self, заменяя элемент значением, возвращаемым блоком.

См. также Enumerable#collect.

Если блок не задан, вместо него возвращается Перечислитель.

a = [ "a", "b", "c", "d" ]
a.map! {|x| x + "!" }
a #=>  [ "a!", "b!", "c!", "d!" ]
a.collect!.with_index {|x, i| x[0...i] }
a #=>  ["", "b", "c!", "d!"]
combination(n) { |комбинация| блок } → массив Показать исходный код
combination(n) → Перечислитель
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;
}

При вызове с блоком, выводит все комбинации длины n элементов из массива, а затем возвращает сам массив.

Реализация не гарантирует порядок, в котором выводятся комбинации.

Если блок не задан, вместо него возвращается Перечислитель.

Примеры:

a = [1, 2, 3, 4]
a.combination(1).to_a  #=> [[1],[2],[3],[4]]
a.combination(2).to_a  #=> [[1,2],[1,3],[1,4],[2,3],[2,4],[3,4]]
a.combination(3).to_a  #=> [[1,2,3],[1,2,4],[1,3,4],[2,3,4]]
a.combination(4).to_a  #=> [[1,2,3,4]]
a.combination(0).to_a  #=> [[]] # one combination of length 0
a.combination(5).to_a  #=> []   # no combinations of length 5
compact → новый_массив Показать исходный код
static VALUE
rb_ary_compact(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_compact_bang(ary);
    return ary;
}

Возвращает копию self с удаленными всеми элементами nil.

[ "a", nil, "b", nil, "c", nil ].compact
                  #=> [ "a", "b", "c" ]
compact! → массив или nil Показать исходный код
static VALUE
rb_ary_compact_bang(VALUE ary)
{
    VALUE *p, *t, *end;
    long n;

    rb_ary_modify(ary);
    p = t = (VALUE *)RARRAY_CONST_PTR(ary); /* WB: no new reference */
    end = p + RARRAY_LEN(ary);

    while (t < end) {
        if (NIL_P(*t)) t++;
        else *p++ = *t++;
    }
    n = p - RARRAY_CONST_PTR(ary);
    if (RARRAY_LEN(ary) == n) {
        return Qnil;
    }
    ary_resize_smaller(ary, n);

    return ary;
}

Удаляет элементы nil из массива.

Возвращает nil если изменений не было, в противном случае возвращает массив.

[ "a", nil, "b", nil, "c" ].compact! #=> [ "a", "b", "c" ]
[ "a", "b", "c" ].compact!           #=> nil
concat(другой_массив) → массив Показать исходный код
VALUE
rb_ary_concat(VALUE x, VALUE y)
{
    rb_ary_modify_check(x);
    y = to_ary(y);
    if (RARRAY_LEN(y) > 0) {
        rb_ary_splice(x, RARRAY_LEN(x), 0, y);
    }
    return x;
}

Добавляет элементы other_ary в self.

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

См. также Array#+.

count → целое Показать исходный код
count(объект) → целое
count { |элемент| блок } → целое
static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long i, n = 0;

    if (argc == 0) {
        VALUE v;

        if (!rb_block_given_p())
            return LONG2NUM(RARRAY_LEN(ary));

        for (i = 0; i < RARRAY_LEN(ary); i++) {
            v = RARRAY_AREF(ary, i);
            if (RTEST(rb_yield(v))) n++;
        }
    }
    else {
        VALUE obj;

        rb_scan_args(argc, argv, "1", &obj);
        if (rb_block_given_p()) {
            rb_warn("given block not used");
        }
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            if (rb_equal(RARRAY_AREF(ary, i), obj)) n++;
        }
    }

    return LONG2NUM(n);
}

Возвращает количество элементов.

Если аргумент задан, подсчитывает количество элементов, равных obj с использованием ==.

Если задан блок, подсчитывает количество элементов, для которых блок возвращает значение true.

ary = [1, 2, 4, 2]
ary.count                  #=> 4
ary.count(2)               #=> 2
ary.count { |x| x%2 == 0 } #=> 3
cycle(n=nil) { |объект| блок } → nil Показать исходный код
cycle(n=nil) → Перечислитель
static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
{
    long n, i;
    VALUE nv = Qnil;

    rb_scan_args(argc, argv, "01", &nv);

    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_cycle_size);
    if (NIL_P(nv)) {
        n = -1;
    }
    else {
        n = NUM2LONG(nv);
        if (n <= 0) return Qnil;
    }

    while (RARRAY_LEN(ary) > 0 && (n < 0 || 0 < n--)) {
        for (i=0; i<RARRAY_LEN(ary); i++) {
            rb_yield(RARRAY_AREF(ary, i));
        }
    }
    return Qnil;
}

Вызывает заданный блок для каждого элемента n раз или бесконечно, если nil задано.

Не делает ничего, если задано не положительное число или массив пустой.

Возвращает nil если цикл завершился без прерывания.

Если блок не задан, вместо него возвращается Перечислитель.

a = ["a", "b", "c"]
a.cycle { |x| puts x }     # print, a, b, c, a, b, c,.. forever.
a.cycle(2) { |x| puts x }  # print, a, b, c, a, b, c.
dclone() Показать исходный код
# File lib/rexml/xpath_parser.rb, line 32
def dclone
  klone = self.clone
  klone.clear
  self.each{|v| klone << v.dclone}
  klone
end

предоставляет объединенную clone операцию для REXML::XPathParser для использования через несколько типов Object+

delete(объект) → элемент или nil Показать исходный код
delete(объект) { блок } → элемент или результат блока
VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
    VALUE v = item;
    long i1, i2;

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

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

    ary_resize_smaller(ary, i2);

    return v;
}

Удаляет все элементы из self , которые равны obj.

Возвращает последний удаленный элемент или nil , если соответствующий элемент не найден.

Если задан необязательный блок кода, возвращается результат блока, если элемент не найден. (Чтобы удалить элементы nil и получить информативное возвращаемое значение, используйте #compact!)

a = [ "a", "b", "b", "b", "c" ]
a.delete("b")                   #=> "b"
a                               #=> ["a", "c"]
a.delete("z")                   #=> nil
a.delete("z") { "not found" }   #=> "not found"
delete_at(индекс) → объект или nil Показать исходный код
static VALUE
rb_ary_delete_at_m(VALUE ary, VALUE pos)
{
    return rb_ary_delete_at(ary, NUM2LONG(pos));
}

Удаляет элемент по указанному index, возвращая этот элемент или nil , если index выходит за пределы диапазона.

См. также #slice!

a = ["ant", "bat", "cat", "dog"]
a.delete_at(2)    #=> "cat"
a                 #=> ["ant", "bat", "dog"]
a.delete_at(99)   #=> nil
delete_if { |элемент| блок } → массив Показать исходный код
delete_if → Перечислитель
static VALUE
rb_ary_delete_if(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    ary_reject_bang(ary);
    return ary;
}

Удаляет каждый элемент из self, для которого блок оценивается как true.

Массив изменяется мгновенно каждый раз, когда вызывается блок, а не после завершения итерации.

См. также #reject!

Если блок не задан, вместо него возвращается Перечислитель.

scores = [ 97, 42, 75 ]
scores.delete_if {|score| score < 80 }   #=> [97]
drop(n) → новый_массив Показать исходный код
static VALUE
rb_ary_drop(VALUE ary, VALUE n)
{
    VALUE result;
    long pos = NUM2LONG(n);
    if (pos < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }

    result = rb_ary_subseq(ary, pos, RARRAY_LEN(ary));
    if (result == Qnil) result = rb_ary_new();
    return result;
}

Удаляет первые n элементы из ary и возвращает оставшиеся элементы в массиве.

Если задано отрицательное число, генерируется исключение ArgumentError.

См. также #take

a = [1, 2, 3, 4, 5, 0]
a.drop(3)             #=> [4, 5, 0]
drop_while { |arr| block } → new_ary Показать исходный код
drop_while → 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));
}

Опускает элементы до, но не включая, первого элемента, для которого блок возвращает nil или false, и возвращает массив, содержащий оставшиеся элементы.

Если блок не задан, возвращается Enumerator.

См. также #take_while

a = [1, 2, 3, 4, 5, 0]
a.drop_while {|i| i < 3 }   #=> [3, 4, 5, 0]
each { |item| block } → ary Показать исходный код
each → Enumerator
VALUE
rb_ary_each(VALUE array)
{
    long i;
    volatile VALUE ary = array;

    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;
}

Вызывает заданный блок один раз для каждого элемента в self, передавая этот элемент в качестве параметра.

Если блок не задан, возвращается Enumerator.

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

дает:

a -- b -- c --
each_index { |index| block } → ary Показать исходный код
each_index → 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;
}

Аналогично #each, но передаёт index элемента вместо самого элемента.

Если блок не задан, возвращается Enumerator.

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

дает:

0 -- 1 -- 2 --
empty? → true or false Показать исходный код
static VALUE
rb_ary_empty_p(VALUE ary)
{
    if (RARRAY_LEN(ary) == 0)
        return Qtrue;
    return Qfalse;
}

Возвращает true , если self не содержит элементов.

[].empty?   #=> true
eql?(other) → true or false Показать исходный код
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);
}

Возвращает true , если self и other — один и тот же объект или оба являются массивами с одинаковым содержимым (в соответствии с Object#eql?).

fetch(index) → obj Показать исходный код
fetch(index, default) → obj
fetch(index) { |index| block } → obj
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);
}

Попытка вернуть элемент в позиции index, но выбросить исключение IndexError, если указанный index выходит за пределы массива. Это исключение можно предотвратить, указав второй аргумент, который будет использоваться в качестве default значения.

В качестве альтернативы, если задан блок, он будет выполнен только при обращении к неверному index значению. Отрицательные значения index отсчитываются от конца массива.

a = [ 11, 22, 33, 44 ]
a.fetch(1)               #=> 22
a.fetch(-1)              #=> 44
a.fetch(4, 'cat')        #=> "cat"
a.fetch(100) { |i| puts "#{i} is out of bounds" }
                         #=> "100 is out of bounds"
fill(obj) → ary Показать исходный код
fill(obj, start [, length]) → ary
fill(obj, range ) → ary
fill { |index| block } → ary
fill(start [, length] ) { |index| block } → ary
fill(range) { |index| block } → ary
static VALUE
rb_ary_fill(int argc, VALUE *argv, VALUE ary)
{
    VALUE item, arg1, arg2;
    long beg = 0, end = 0, len = 0;
    int block_p = FALSE;

    if (rb_block_given_p()) {
        block_p = TRUE;
        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 (block_p) {
        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;
}

Первые три формы устанавливают выбранные элементы массива self (которые могут быть всем массивом) на obj.

Значение start nil равно нулю.

Значение length nil равно длине массива.

Последние три формы заполняют массив значением заданного блока, которому передаётся абсолютный индекс каждого заполняемого элемента.

Отрицательные значения start отсчитываются от конца массива, где -1 — это последний элемент.

a = [ "a", "b", "c", "d" ]
a.fill("x")              #=> ["x", "x", "x", "x"]
a.fill("z", 2, 2)        #=> ["x", "x", "z", "z"]
a.fill("y", 0..1)        #=> ["y", "y", "z", "z"]
a.fill { |i| i*i }       #=> [0, 1, 4, 9]
a.fill(-2) { |i| i*i*i } #=> [0, 1, 8, 27]
find_index(obj) → int or nil Показать исходный код
find_index { |item| block } → int or nil
find_index → Enumerator
static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
    const VALUE *ptr;
    VALUE val;
    long i, len;

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

Возвращает индекс первого объекта в ary, такого, что объект == с obj.

Если вместо аргумента задан блок, возвращает индекс первого объекта, для которого блок возвращает true. Возвращает nil , если соответствие не найдено.

См. также #rindex.

Если ни блок, ни аргумент не заданы, возвращается Enumerator.

a = [ "a", "b", "c" ]
a.index("b")              #=> 1
a.index("z")              #=> nil
a.index { |x| x == "b" }  #=> 1
first → obj or nil Показать исходный код
first(n) → new_ary
static VALUE
rb_ary_first(int argc, VALUE *argv, VALUE ary)
{
    if (argc == 0) {
        if (RARRAY_LEN(ary) == 0) return Qnil;
        return RARRAY_AREF(ary, 0);
    }
    else {
        return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    }
}

Возвращает первый элемент или первые n элементов массива. Если массив пуст, первая форма возвращает nil, а вторая форма возвращает пустой массив. См. также #last для обратного эффекта.

a = [ "q", "r", "s", "t" ]
a.first     #=> "q"
a.first(2)  #=> ["q", "r"]
flatten → new_ary Показать исходный код
flatten(level) → new_ary
static VALUE
rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
{
    int mod = 0, level = -1;
    VALUE result, lv;

    rb_scan_args(argc, argv, "01", &lv);
    if (!NIL_P(lv)) level = NUM2INT(lv);
    if (level == 0) return ary_make_shared_copy(ary);

    result = flatten(ary, level, &mod);
    OBJ_INFECT(result, ary);

    return result;
}

Возвращает новый массив, являющийся одноуровневым развёртыванием self (рекурсивно).

То есть, для каждого элемента, который является массивом, извлекает его элементы в новый массив.

Необязательный аргумент level определяет уровень рекурсии для развёртывания.

s = [ 1, 2, 3 ]           #=> [1, 2, 3]
t = [ 4, 5, 6, [7, 8] ]   #=> [4, 5, 6, [7, 8]]
a = [ s, t, 9, 10 ]       #=> [[1, 2, 3], [4, 5, 6, [7, 8]], 9, 10]
a.flatten                 #=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten(1)              #=> [1, 2, 3, [4, 5]]
flatten! → ary or nil Показать исходный код
flatten!(level) → ary or nil
static VALUE
rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
{
    int mod = 0, level = -1;
    VALUE result, lv;

    rb_scan_args(argc, argv, "01", &lv);
    rb_ary_modify_check(ary);
    if (!NIL_P(lv)) level = NUM2INT(lv);
    if (level == 0) return Qnil;

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

    return ary;
}

Развертывает self на месте.

Возвращает nil , если изменения не были внесены (т.е. массив не содержит подмассивов).

Необязательный аргумент level определяет уровень рекурсии для развёртывания.

a = [ 1, 2, [3, [4, 5] ] ]
a.flatten!   #=> [1, 2, 3, 4, 5]
a.flatten!   #=> nil
a            #=> [1, 2, 3, 4, 5]
a = [ 1, 2, [3, [4, 5] ] ]
a.flatten!(1) #=> [1, 2, 3, [4, 5]]
frozen? → true or false Показать исходный код
static VALUE
rb_ary_frozen_p(VALUE ary)
{
    if (OBJ_FROZEN(ary)) return Qtrue;
    return Qfalse;
}

Возвращает true , если этот массив заморожен (или временно заморожен во время сортировки). См. также Object#frozen?

hash → fixnum Показать исходный код
static VALUE
rb_ary_hash(VALUE ary)
{
    long i;
    st_index_t h;
    VALUE n;

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

Вычисляет хэш-код для этого массива.

Два массива с одинаковым содержимым будут иметь одинаковый хэш-код (и будут сравниваться с помощью eql?).

См. также Object#hash.

include?(object) → true or false Показать исходный код
VALUE
rb_ary_includes(VALUE ary, VALUE item)
{
    long i;
    VALUE e;

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

Возвращает true , если заданный object присутствует в self (то есть, если какой-либо элемент == object), в противном случае возвращает false.

a = [ "a", "b", "c" ]
a.include?("b")   #=> true
a.include?("z")   #=> false
index(obj) → int or nil Show source
index { |item| block } → int or nil
index → Enumerator
static VALUE
rb_ary_index(int argc, VALUE *argv, VALUE ary)
{
    const VALUE *ptr;
    VALUE val;
    long i, len;

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

Возвращает индекс первого объекта в ary такого, что объект == к obj.

Если вместо аргумента задан блок, возвращает индекс первого объекта, для которого блок возвращает true. Возвращает nil если совпадений не найдено.

См. также #rindex.

Если не задан ни блок, ни аргумент, возвращается Enumerator.

a = [ "a", "b", "c" ]
a.index("b")              #=> 1
a.index("z")              #=> nil
a.index { |x| x == "b" }  #=> 1
initialize_copy(other_ary) → ary Show source
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
    rb_ary_modify_check(copy);
    orig = to_ary(orig);
    if (copy == orig) return copy;

    if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
        VALUE shared = 0;

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

Заменяет содержимое self содержимым other_ary, усекая или расширяя при необходимости.

a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
a                              #=> ["x", "y", "z"]
insert(index, obj...) → ary Show source
static VALUE
rb_ary_insert(int argc, VALUE *argv, VALUE ary)
{
    long pos;

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    rb_ary_modify_check(ary);
    if (argc == 1) return ary;
    pos = NUM2LONG(argv[0]);
    if (pos == -1) {
        pos = RARRAY_LEN(ary);
    }
    if (pos < 0) {
        pos++;
    }
    rb_ary_splice(ary, pos, 0, rb_ary_new4(argc - 1, argv + 1));
    return ary;
}

Вставляет заданные значения перед элементом с заданным index.

Отрицательные индексы отсчитываются от конца массива, где -1 является последним элементом. Если используется отрицательный индекс, заданные значения будут вставлены после этого элемента, поэтому использование индекса -1 вставит значения в конец массива.

a = %w{ a b c d }
a.insert(2, 99)         #=> ["a", "b", 99, "c", "d"]
a.insert(-2, 1, 2, 3)   #=> ["a", "b", 99, "c", 1, 2, 3, "d"]
inspect → string Show source
to_s → string
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);
}

Создает строковое представление self.

[ "a", "b", "c" ].to_s     #=> "[\"a\", \"b\", \"c\"]"
Также используется как: to_s
join(separator=$,) → str Show source
static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE sep;

    rb_scan_args(argc, argv, "01", &sep);
    if (NIL_P(sep)) sep = rb_output_fs;

    return rb_ary_join(ary, sep);
}

Возвращает строку, созданную путем преобразования каждого элемента массива в строку, разделенную заданным separator. Если separator является nil, используется текущий $,. Если и separator, и $, равны nil, используется пустая строка.

[ "a", "b", "c" ].join        #=> "abc"
[ "a", "b", "c" ].join("-")   #=> "a-b-c"
keep_if { |item| block } → ary Show source
keep_if → 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;
}

Удаляет каждый элемент self, для которого данный блок вычисляет значение false.

См. также #select!

Если блок не задан, вместо этого возвращается Enumerator.

a = %w{ a b c d e f }
a.keep_if { |v| v =~ /[aeiou]/ }  #=> ["a", "e"]
last → obj or nil Show source
last(n) → new_ary
VALUE
rb_ary_last(int argc, const VALUE *argv, VALUE ary)
{
    if (argc == 0) {
        long len = RARRAY_LEN(ary);
        if (len == 0) return Qnil;
        return RARRAY_AREF(ary, len-1);
    }
    else {
        return ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
    }
}

Возвращает последний(ие) элемент(ы) self. Если массив пуст, первая форма возвращает nil.

См. также #first для обратного эффекта.

a = [ "w", "x", "y", "z" ]
a.last     #=> "z"
a.last(2)  #=> ["y", "z"]
length → int Show source
static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

Возвращает количество элементов в self. Может быть равно нулю.

[ 1, 2, 3, 4, 5 ].length   #=> 5
[].length                  #=> 0
Также используется как: size
map { |item| block } → new_ary Show source
map → Enumerator
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;
}

Вызывает заданный блок один раз для каждого элемента self.

Создает новый массив, содержащий значения, возвращаемые блоком.

См. также Enumerable#collect.

Если блок не задан, вместо этого возвращается Enumerator.

a = [ "a", "b", "c", "d" ]
a.collect { |x| x + "!" }        #=> ["a!", "b!", "c!", "d!"]
a.map.with_index{ |x, i| x * i } #=> ["", "b", "cc", "ddd"]
a                                #=> ["a", "b", "c", "d"]
map! {|item| block } → ary Show source
map! → Enumerator
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;
}

Вызывает заданный блок один раз для каждого элемента self, заменяя элемент значением, возвращаемым блоком.

См. также Enumerable#collect.

Если блок не задан, вместо этого возвращается Enumerator.

a = [ "a", "b", "c", "d" ]
a.map! {|x| x + "!" }
a #=>  [ "a!", "b!", "c!", "d!" ]
a.collect!.with_index {|x, i| x[0...i] }
a #=>  ["", "b", "c!", "d!"]
pack ( aTemplateString ) → aBinaryString Show source
static VALUE
pack_pack(VALUE ary, VALUE fmt)
{
    static const char nul10[] = "\0\0\0\0\0\0\0\0\0\0";
    static const char spc10[] = "          ";
    const char *p, *pend;
    VALUE res, from, associates = 0;
    char type;
    long items, len, idx, plen;
    const char *ptr;
    int enc_info = 1;           /* 0 - BINARY, 1 - US-ASCII, 2 - UTF-8 */
#ifdef NATINT_PACK
    int natint;         /* native integer */
#endif
    int integer_size, bigendian_p;

    StringValue(fmt);
    p = RSTRING_PTR(fmt);
    pend = p + RSTRING_LEN(fmt);
    res = rb_str_buf_new(0);

    items = RARRAY_LEN(ary);
    idx = 0;

#define TOO_FEW (rb_raise(rb_eArgError, toofew), 0)
#define THISFROM (items > 0 ? RARRAY_AREF(ary, idx) : TOO_FEW)
#define NEXTFROM (items-- > 0 ? RARRAY_AREF(ary, idx++) : TOO_FEW)

    while (p < pend) {
        int explicit_endian = 0;
        if (RSTRING_PTR(fmt) + RSTRING_LEN(fmt) != pend) {
            rb_raise(rb_eRuntimeError, "format string modified");
        }
        type = *p++;           /* get data type */
#ifdef NATINT_PACK
        natint = 0;
#endif

        if (ISSPACE(type)) continue;
        if (type == '#') {
            while ((p < pend) && (*p != '\n')) {
                p++;
            }
            continue;
        }

        {
          modifiers:
            switch (*p) {
              case '_':
              case '!':
                if (strchr(natstr, type)) {
#ifdef NATINT_PACK
                    natint = 1;
#endif
                    p++;
                }
                else {
                    rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, natstr);
                }
                goto modifiers;

              case '<':
              case '>':
                if (!strchr(endstr, type)) {
                    rb_raise(rb_eArgError, "'%c' allowed only after types %s", *p, endstr);
                }
                if (explicit_endian) {
                    rb_raise(rb_eRangeError, "Can't use both '<' and '>'");
                }
                explicit_endian = *p++;
                goto modifiers;
            }
        }

        if (*p == '*') {       /* set data length */
            len = strchr("@Xxu", type) ? 0
                : strchr("PMm", type) ? 1
                : items;
            p++;
        }
        else if (ISDIGIT(*p)) {
            errno = 0;
            len = STRTOUL(p, (char**)&p, 10);
            if (errno) {
                rb_raise(rb_eRangeError, "pack length too big");
            }
        }
        else {
            len = 1;
        }

        switch (type) {
          case 'U':
            /* if encoding is US-ASCII, upgrade to UTF-8 */
            if (enc_info == 1) enc_info = 2;
            break;
          case 'm': case 'M': case 'u':
            /* keep US-ASCII (do nothing) */
            break;
          default:
            /* fall back to BINARY */
            enc_info = 0;
            break;
        }
        switch (type) {
          case 'A': case 'a': case 'Z':
          case 'B': case 'b':
          case 'H': case 'h':
            from = NEXTFROM;
            if (NIL_P(from)) {
                ptr = "";
                plen = 0;
            }
            else {
                StringValue(from);
                ptr = RSTRING_PTR(from);
                plen = RSTRING_LEN(from);
                OBJ_INFECT(res, from);
            }

            if (p[-1] == '*')
                len = plen;

            switch (type) {
              case 'a':                /* arbitrary binary string (null padded)  */
              case 'A':         /* arbitrary binary string (ASCII space padded) */
              case 'Z':         /* null terminated string  */
                if (plen >= len) {
                    rb_str_buf_cat(res, ptr, len);
                    if (p[-1] == '*' && type == 'Z')
                        rb_str_buf_cat(res, nul10, 1);
                }
                else {
                    rb_str_buf_cat(res, ptr, plen);
                    len -= plen;
                    while (len >= 10) {
                        rb_str_buf_cat(res, (type == 'A')?spc10:nul10, 10);
                        len -= 10;
                    }
                    rb_str_buf_cat(res, (type == 'A')?spc10:nul10, len);
                }
                break;

#define castchar(from) (char)((from) & 0xff)

              case 'b':                /* bit string (ascending) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len - plen + 1)/2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        if (*ptr & 1)
                            byte |= 128;
                        if (i & 7)
                            byte >>= 1;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 7) {
                        char c;
                        byte >>= 7 - (len & 7);
                        c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;

              case 'B':                /* bit string (descending) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len - plen + 1)/2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        byte |= *ptr & 1;
                        if (i & 7)
                            byte <<= 1;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 7) {
                        char c;
                        byte <<= 7 - (len & 7);
                        c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;

              case 'h':                /* hex string (low nibble first) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len + 1) / 2 - (plen + 1) / 2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        if (ISALPHA(*ptr))
                            byte |= (((*ptr & 15) + 9) & 15) << 4;
                        else
                            byte |= (*ptr & 15) << 4;
                        if (i & 1)
                            byte >>= 4;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 1) {
                        char c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;

              case 'H':                /* hex string (high nibble first) */
                {
                    int byte = 0;
                    long i, j = 0;

                    if (len > plen) {
                        j = (len + 1) / 2 - (plen + 1) / 2;
                        len = plen;
                    }
                    for (i=0; i++ < len; ptr++) {
                        if (ISALPHA(*ptr))
                            byte |= ((*ptr & 15) + 9) & 15;
                        else
                            byte |= *ptr & 15;
                        if (i & 1)
                            byte <<= 4;
                        else {
                            char c = castchar(byte);
                            rb_str_buf_cat(res, &c, 1);
                            byte = 0;
                        }
                    }
                    if (len & 1) {
                        char c = castchar(byte);
                        rb_str_buf_cat(res, &c, 1);
                    }
                    len = j;
                    goto grow;
                }
                break;
            }
            break;

          case 'c':            /* signed char */
          case 'C':            /* unsigned char */
            integer_size = 1;
            bigendian_p = BIGENDIAN_P(); /* not effective */
            goto pack_integer;

          case 's':            /* s for int16_t, s! for signed short */
            integer_size = NATINT_LEN(short, 2);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'S':            /* S for uint16_t, S! for unsigned short */
            integer_size = NATINT_LEN(short, 2);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'i':            /* i and i! for signed int */
            integer_size = (int)sizeof(int);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'I':            /* I and I! for unsigned int */
            integer_size = (int)sizeof(int);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'l':            /* l for int32_t, l! for signed long */
            integer_size = NATINT_LEN(long, 4);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'L':            /* L for uint32_t, L! for unsigned long */
            integer_size = NATINT_LEN(long, 4);
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'q':            /* q for int64_t, q! for signed long long */
            integer_size = NATINT_LEN_Q;
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'Q':            /* Q for uint64_t, Q! for unsigned long long */
            integer_size = NATINT_LEN_Q;
            bigendian_p = BIGENDIAN_P();
            goto pack_integer;

          case 'n':            /* 16 bit (2 bytes) integer (network byte-order)  */
            integer_size = 2;
            bigendian_p = 1;
            goto pack_integer;

          case 'N':            /* 32 bit (4 bytes) integer (network byte-order) */
            integer_size = 4;
            bigendian_p = 1;
            goto pack_integer;

          case 'v':            /* 16 bit (2 bytes) integer (VAX byte-order) */
            integer_size = 2;
            bigendian_p = 0;
            goto pack_integer;

          case 'V':            /* 32 bit (4 bytes) integer (VAX byte-order) */
            integer_size = 4;
            bigendian_p = 0;
            goto pack_integer;

          pack_integer:
            if (explicit_endian) {
                bigendian_p = explicit_endian == '>';
            }
            if (integer_size > MAX_INTEGER_PACK_SIZE)
                rb_bug("unexpected intger size for pack: %d", integer_size);
            while (len-- > 0) {
                char intbuf[MAX_INTEGER_PACK_SIZE];

                from = NEXTFROM;
                rb_integer_pack(from, intbuf, integer_size, 1, 0,
                    INTEGER_PACK_2COMP |
                    (bigendian_p ? INTEGER_PACK_BIG_ENDIAN : INTEGER_PACK_LITTLE_ENDIAN));
                rb_str_buf_cat(res, intbuf, integer_size);
            }
            break;

          case 'f':            /* single precision float in native format */
          case 'F':            /* ditto */
            while (len-- > 0) {
                float f;

                from = NEXTFROM;
                f = (float)RFLOAT_VALUE(rb_to_float(from));
                rb_str_buf_cat(res, (char*)&f, sizeof(float));
            }
            break;

          case 'e':            /* single precision float in VAX byte-order */
            while (len-- > 0) {
                FLOAT_CONVWITH(tmp);

                from = NEXTFROM;
                tmp.f = (float)RFLOAT_VALUE(rb_to_float(from));
                HTOVF(tmp);
                rb_str_buf_cat(res, tmp.buf, sizeof(float));
            }
            break;

          case 'E':            /* double precision float in VAX byte-order */
            while (len-- > 0) {
                DOUBLE_CONVWITH(tmp);
                from = NEXTFROM;
                tmp.d = RFLOAT_VALUE(rb_to_float(from));
                HTOVD(tmp);
                rb_str_buf_cat(res, tmp.buf, sizeof(double));
            }
            break;

          case 'd':            /* double precision float in native format */
          case 'D':            /* ditto */
            while (len-- > 0) {
                double d;

                from = NEXTFROM;
                d = RFLOAT_VALUE(rb_to_float(from));
                rb_str_buf_cat(res, (char*)&d, sizeof(double));
            }
            break;

          case 'g':            /* single precision float in network byte-order */
            while (len-- > 0) {
                FLOAT_CONVWITH(tmp);
                from = NEXTFROM;
                tmp.f = (float)RFLOAT_VALUE(rb_to_float(from));
                HTONF(tmp);
                rb_str_buf_cat(res, tmp.buf, sizeof(float));
            }
            break;

          case 'G':            /* double precision float in network byte-order */
            while (len-- > 0) {
                DOUBLE_CONVWITH(tmp);

                from = NEXTFROM;
                tmp.d = RFLOAT_VALUE(rb_to_float(from));
                HTOND(tmp);
                rb_str_buf_cat(res, tmp.buf, sizeof(double));
            }
            break;

          case 'x':            /* null byte */
          grow:
            while (len >= 10) {
                rb_str_buf_cat(res, nul10, 10);
                len -= 10;
            }
            rb_str_buf_cat(res, nul10, len);
            break;

          case 'X':            /* back up byte */
          shrink:
            plen = RSTRING_LEN(res);
            if (plen < len)
                rb_raise(rb_eArgError, "X outside of string");
            rb_str_set_len(res, plen - len);
            break;

          case '@':            /* null fill to absolute position */
            len -= RSTRING_LEN(res);
            if (len > 0) goto grow;
            len = -len;
            if (len > 0) goto shrink;
            break;

          case '%':
            rb_raise(rb_eArgError, "%% is not supported");
            break;

          case 'U':            /* Unicode character */
            while (len-- > 0) {
                SIGNED_VALUE l;
                char buf[8];
                int le;

                from = NEXTFROM;
                from = rb_to_int(from);
                l = NUM2LONG(from);
                if (l < 0) {
                    rb_raise(rb_eRangeError, "pack(U): value out of range");
                }
                le = rb_uv_to_utf8(buf, l);
                rb_str_buf_cat(res, (char*)buf, le);
            }
            break;

          case 'u':            /* uuencoded string */
          case 'm':            /* base64 encoded string */
            from = NEXTFROM;
            StringValue(from);
            ptr = RSTRING_PTR(from);
            plen = RSTRING_LEN(from);

            if (len == 0 && type == 'm') {
                encodes(res, ptr, plen, type, 0);
                ptr += plen;
                break;
            }
            if (len <= 2)
                len = 45;
            else if (len > 63 && type == 'u')
                len = 63;
            else
                len = len / 3 * 3;
            while (plen > 0) {
                long todo;

                if (plen > len)
                    todo = len;
                else
                    todo = plen;
                encodes(res, ptr, todo, type, 1);
                plen -= todo;
                ptr += todo;
            }
            break;

          case 'M':            /* quoted-printable encoded string */
            from = rb_obj_as_string(NEXTFROM);
            if (len <= 1)
                len = 72;
            qpencode(res, from, len);
            break;

          case 'P':            /* pointer to packed byte string */
            from = THISFROM;
            if (!NIL_P(from)) {
                StringValue(from);
                if (RSTRING_LEN(from) < len) {
                    rb_raise(rb_eArgError, "too short buffer for P(%ld for %ld)",
                             RSTRING_LEN(from), len);
                }
            }
            len = 1;
            /* FALL THROUGH */
          case 'p':            /* pointer to string */
            while (len-- > 0) {
                char *t;
                from = NEXTFROM;
                if (NIL_P(from)) {
                    t = 0;
                }
                else {
                    t = StringValuePtr(from);
                    rb_obj_taint(from);
                }
                if (!associates) {
                    associates = rb_ary_new();
                }
                rb_ary_push(associates, from);
                rb_str_buf_cat(res, (char*)&t, sizeof(char*));
            }
            break;

          case 'w':            /* BER compressed integer  */
            while (len-- > 0) {
                VALUE buf = rb_str_new(0, 0);
                size_t numbytes;
                int sign;
                char *cp;

                from = NEXTFROM;
                from = rb_to_int(from);
                numbytes = rb_absint_numwords(from, 7, NULL);
                if (numbytes == 0)
                    numbytes = 1;
                buf = rb_str_new(NULL, numbytes);

                sign = rb_integer_pack(from, RSTRING_PTR(buf), RSTRING_LEN(buf), 1, 1, INTEGER_PACK_BIG_ENDIAN);

                if (sign < 0)
                    rb_raise(rb_eArgError, "can't compress negative numbers");
                if (sign == 2)
                    rb_bug("buffer size problem?");

                cp = RSTRING_PTR(buf);
                while (1 < numbytes) {
                  *cp |= 0x80;
                  cp++;
                  numbytes--;
                }

                rb_str_buf_cat(res, RSTRING_PTR(buf), RSTRING_LEN(buf));
            }
            break;

          default: {
            char unknown[5];
            if (ISPRINT(type)) {
                unknown[0] = type;
                unknown[1] = '\0';
            }
            else {
                snprintf(unknown, sizeof(unknown), "\\x%.2x", type & 0xff);
            }
            rb_warning("unknown pack directive '%s' in '% "PRIsVALUE"'",
                       unknown, fmt);
            break;
          }
        }
    }

    if (associates) {
        str_associate(res, associates);
    }
    OBJ_INFECT(res, fmt);
    switch (enc_info) {
      case 1:
        ENCODING_CODERANGE_SET(res, rb_usascii_encindex(), ENC_CODERANGE_7BIT);
        break;
      case 2:
        rb_enc_set_index(res, rb_utf8_encindex());
        break;
      default:
        /* do nothing, keep ASCII-8BIT */
        break;
    }
    return res;
}

Упаковывает содержимое arr в двоичную последовательность в соответствии с директивами в aTemplateString (см. таблицу ниже) Директивы “A,'' “a,'' и “Z'' могут сопровождаться счетчиком, который задает ширину результирующего поля. Остальные директивы также могут принимать счетчик, указывающий количество элементов массива для преобразования. Если счетчик является звездочкой (“*''), будут преобразованы все оставшиеся элементы массива. Любая из директив “sSiIlL'' может сопровождаться подчеркиванием (“_'') или восклицательным знаком (“!'') для использования собственного размера базовой платформы для указанного типа; в противном случае они используют платформонезависимый размер. Пробелы игнорируются в строке шаблона. См. также String#unpack.

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

Директивы для pack.

Integer      | Array   |
Directive    | Element | Meaning
---------------------------------------------------------------------------
   C         | Integer | 8-bit unsigned (unsigned char)
   S         | Integer | 16-bit unsigned, native endian (uint16_t)
   L         | Integer | 32-bit unsigned, native endian (uint32_t)
   Q         | Integer | 64-bit unsigned, native endian (uint64_t)
             |         |
   c         | Integer | 8-bit signed (signed char)
   s         | Integer | 16-bit signed, native endian (int16_t)
   l         | Integer | 32-bit signed, native endian (int32_t)
   q         | Integer | 64-bit signed, native endian (int64_t)
             |         |
   S_, S!    | Integer | unsigned short, native endian
   I, I_, I! | Integer | unsigned int, native endian
   L_, L!    | Integer | unsigned long, native endian
   Q_, Q!    | Integer | unsigned long long, native endian (ArgumentError
             |         | if the platform has no long long type.)
             |         | (Q_ and Q! is available since Ruby 2.1.)
             |         |
   s_, s!    | Integer | signed short, native endian
   i, i_, i! | Integer | signed int, native endian
   l_, l!    | Integer | signed long, native endian
   q_, q!    | Integer | signed long long, native endian (ArgumentError
             |         | if the platform has no long long type.)
             |         | (q_ and q! is available since Ruby 2.1.)
             |         |
   S> L> Q>  | Integer | same as the directives without ">" except
   s> l> q>  |         | big endian
   S!> I!>   |         | (available since Ruby 1.9.3)
   L!> Q!>   |         | "S>" is same as "n"
   s!> i!>   |         | "L>" is same as "N"
   l!> q!>   |         |
             |         |
   S< L< Q<  | Integer | same as the directives without "<" except
   s< l< q<  |         | little endian
   S!< I!<   |         | (available since Ruby 1.9.3)
   L!< Q!<   |         | "S<" is same as "v"
   s!< i!<   |         | "L<" is same as "V"
   l!< q!<   |         |
             |         |
   n         | Integer | 16-bit unsigned, network (big-endian) byte order
   N         | Integer | 32-bit unsigned, network (big-endian) byte order
   v         | Integer | 16-bit unsigned, VAX (little-endian) byte order
   V         | Integer | 32-bit unsigned, VAX (little-endian) byte order
             |         |
   U         | Integer | UTF-8 character
   w         | Integer | BER-compressed integer

Float        |         |
Directive    |         | Meaning
---------------------------------------------------------------------------
   D, d      | Float   | double-precision, native format
   F, f      | Float   | single-precision, native format
   E         | Float   | double-precision, little-endian byte order
   e         | Float   | single-precision, little-endian byte order
   G         | Float   | double-precision, network (big-endian) byte order
   g         | Float   | single-precision, network (big-endian) byte order

String       |         |
Directive    |         | Meaning
---------------------------------------------------------------------------
   A         | String  | arbitrary binary string (space padded, count is width)
   a         | String  | arbitrary binary string (null padded, count is width)
   Z         | String  | same as ``a'', except that null is added with *
   B         | String  | bit string (MSB first)
   b         | String  | bit string (LSB first)
   H         | String  | hex string (high nibble first)
   h         | String  | hex string (low nibble first)
   u         | String  | UU-encoded string
   M         | String  | quoted printable, MIME encoding (see RFC2045)
   m         | String  | base64 encoded string (see RFC 2045, count is width)
             |         | (if count is 0, no line feed are added, see RFC 4648)
   P         | String  | pointer to a structure (fixed-length string)
   p         | String  | pointer to a null-terminated string

Misc.        |         |
Directive    |         | Meaning
---------------------------------------------------------------------------
   @         | ---     | moves to absolute position
   X         | ---     | back up a byte
   x         | ---     | null byte
permutation { |p| block } → ary Show source
permutation → Enumerator
permutation(n) { |p| block } → ary
permutation(n) → Enumerator
static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
    VALUE num;
    long r, n, i;

    n = RARRAY_LEN(ary);                  /* Array length */
    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);   /* Return enumerator if no block */
    rb_scan_args(argc, argv, "01", &num);
    r = NIL_P(num) ? n : NUM2LONG(num);   /* Permutation size from argument */

    if (r < 0 || n < r) {
        /* no permutations: yield nothing */
    }
    else if (r == 0) { /* exactly one permutation: the zero-length array */
        rb_yield(rb_ary_new2(0));
    }
    else if (r == 1) { /* this is a special, easy case */
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
        }
    }
    else {             /* this is the general case */
        volatile VALUE t0;
        long *p = (long*)ALLOCV(t0, r*sizeof(long)+n*sizeof(char));
        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;
}

При вызове с блоком, выдает все перестановки длины n элементов массива, а затем возвращает сам массив.

Если n не указан, выдает все перестановки всех элементов.

Реализация не гарантирует порядок, в котором выдаются перестановки.

Если блок не задан, вместо этого возвращается Enumerator.

Примеры:

a = [1, 2, 3]
a.permutation.to_a    #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
a.permutation(1).to_a #=> [[1],[2],[3]]
a.permutation(2).to_a #=> [[1,2],[1,3],[2,1],[2,3],[3,1],[3,2]]
a.permutation(3).to_a #=> [[1,2,3],[1,3,2],[2,1,3],[2,3,1],[3,1,2],[3,2,1]]
a.permutation(0).to_a #=> [[]] # one permutation of length 0
a.permutation(4).to_a #=> []   # no permutations of length 4
pop → obj or nil Show source
pop(n) → new_ary
static VALUE
rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE result;

    if (argc == 0) {
        return rb_ary_pop(ary);
    }

    rb_ary_modify_check(ary);
    result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_LAST);
    ARY_INCREASE_LEN(ary, -RARRAY_LEN(result));
    return result;
}

Удаляет последний элемент из self и возвращает его, или nil, если массив пуст.

Если задано число n, возвращает массив из последних n элементов (или меньше), так же как делает array.slice!(-n, n). См. также #push для обратного эффекта.

a = [ "a", "b", "c", "d" ]
a.pop     #=> "d"
a.pop(2)  #=> ["b", "c"]
a         #=> ["a"]
product(other_ary, ...) → new_ary Show source
product(other_ary, ...) { |p| block } → ary
static VALUE
rb_ary_product(int argc, VALUE *argv, VALUE ary)
{
    int n = argc+1;    /* How many arrays we're operating on */
    volatile VALUE t0 = tmpary(n);
    volatile VALUE t1 = tmpbuf(n, sizeof(int));
    VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
    int *counters = (int*)RSTRING_PTR(t1); /* The current position in each one */
    VALUE result = Qnil;      /* The array we'll be returning, when no block given */
    long i,j;
    long resultlen = 1;

    RBASIC_CLEAR_CLASS(t0);
    RBASIC_CLEAR_CLASS(t1);

    /* initialize the arrays of arrays */
    ARY_SET_LEN(t0, n);
    arrays[0] = ary;
    for (i = 1; i < n; i++) arrays[i] = Qnil;
    for (i = 1; i < n; i++) arrays[i] = to_ary(argv[i-1]);

    /* initialize the counters for the arrays */
    for (i = 0; i < n; i++) counters[i] = 0;

    /* Otherwise, allocate and fill in an array of results */
    if (rb_block_given_p()) {
        /* Make defensive copies of arrays; exit if any is empty */
        for (i = 0; i < n; i++) {
            if (RARRAY_LEN(arrays[i]) == 0) goto done;
            arrays[i] = ary_make_shared_copy(arrays[i]);
        }
    }
    else {
        /* Compute the length of the result array; return [] if any is empty */
        for (i = 0; i < n; i++) {
            long k = RARRAY_LEN(arrays[i]);
            if (k == 0) {
                result = rb_ary_new2(0);
                goto done;
            }
            if (MUL_OVERFLOW_LONG_P(resultlen, k))
                rb_raise(rb_eRangeError, "too big to product");
            resultlen *= k;
        }
        result = rb_ary_new2(resultlen);
    }
    for (;;) {
        int m;
        /* fill in one subarray */
        VALUE subarray = rb_ary_new2(n);
        for (j = 0; j < n; j++) {
            rb_ary_push(subarray, rb_ary_entry(arrays[j], counters[j]));
        }

        /* put it on the result array */
        if (NIL_P(result)) {
            FL_SET(t0, FL_USER5);
            rb_yield(subarray);
            if (! FL_TEST(t0, FL_USER5)) {
                rb_raise(rb_eRuntimeError, "product reentered");
            }
            else {
                FL_UNSET(t0, FL_USER5);
            }
        }
        else {
            rb_ary_push(result, subarray);
        }

        /*
         * Increment the last counter.  If it overflows, reset to 0
         * and increment the one before it.
         */
        m = n-1;
        counters[m]++;
        while (counters[m] == RARRAY_LEN(arrays[m])) {
            counters[m] = 0;
            /* If the first counter overflows, we are done */
            if (--m < 0) goto done;
            counters[m]++;
        }
    }
done:
    tmpary_discard(t0);
    tmpbuf_discard(t1);

    return NIL_P(result) ? ary : result;
}

Возвращает массив всех комбинаций элементов из всех массивов.

Длина возвращаемого массива равна произведению длины self и массивов аргументов.

Если задан блок, product будет выдавать все комбинации и возвращать self вместо этого.

[1,2,3].product([4,5])     #=> [[1,4],[1,5],[2,4],[2,5],[3,4],[3,5]]
[1,2].product([1,2])       #=> [[1,1],[1,2],[2,1],[2,2]]
[1,2].product([3,4],[5,6]) #=> [[1,3,5],[1,3,6],[1,4,5],[1,4,6],
                           #     [2,3,5],[2,3,6],[2,4,5],[2,4,6]]
[1,2].product()            #=> [[1],[2]]
[1,2].product([])          #=> []
push(obj, ... ) → ary Show source
static VALUE
rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
{
    return rb_ary_cat(ary, argv, argc);
}

Добавление — Добавляет заданные объекты в конец этого массива. Это выражение возвращает сам массив, поэтому несколько добавлений могут быть связаны вместе. См. также #pop для обратного эффекта.

a = [ "a", "b", "c" ]
a.push("d", "e", "f")
        #=> ["a", "b", "c", "d", "e", "f"]
[1, 2, 3,].push(4).push(5)
        #=> [1, 2, 3, 4, 5]
rassoc(obj) → new_ary or nil Показать исходный код
VALUE
rb_ary_rassoc(VALUE ary, VALUE value)
{
    long i;
    VALUE v;

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

Ищет в массиве, элементы которого также являются массивами.

Сравнивает obj со вторым элементом каждого вложенного массива с помощью obj.==.

Возвращает первый вложенный массив, который соответствует obj.

См. также #assoc.

a = [ [ 1, "one"], [2, "two"], [3, "three"], ["ii", "two"] ]
a.rassoc("two")    #=> [2, "two"]
a.rassoc("four")   #=> nil
reject {|item| block } → new_ary Показать исходный код
reject → 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;
}

Возвращает новый массив, содержащий элементы из self, для которых заданный блок не true.

См. также #delete_if

Если блок не задан, вместо него возвращается Enumerator.

reject! { |item| block } → ary or nil Показать исходный код
reject! → Enumerator
static VALUE
rb_ary_reject_bang(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    return ary_reject_bang(ary);
}

Эквивалентно #delete_if, удаляя элементы из self, для которых блок возвращает true, но возвращает nil если изменений не было.

Массив изменяется мгновенно каждый раз при вызове блока, а не после завершения итерации.

См. также Enumerable#reject и #delete_if.

Если блок не задан, вместо него возвращается Enumerator.

repeated_combination(n) { |c| block } → ary Показать исходный код
repeated_combination(n) → 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;
}

При вызове с блоком генерирует все повторяющиеся сочетания длины n элементов из массива, а затем возвращает сам массив.

Реализация не гарантирует порядок, в котором генерируются повторяющиеся сочетания.

Если блок не задан, вместо него возвращается Enumerator.

Примеры:

a = [1, 2, 3]
a.repeated_combination(1).to_a  #=> [[1], [2], [3]]
a.repeated_combination(2).to_a  #=> [[1,1],[1,2],[1,3],[2,2],[2,3],[3,3]]
a.repeated_combination(3).to_a  #=> [[1,1,1],[1,1,2],[1,1,3],[1,2,2],[1,2,3],
                                #    [1,3,3],[2,2,2],[2,2,3],[2,3,3],[3,3,3]]
a.repeated_combination(4).to_a  #=> [[1,1,1,1],[1,1,1,2],[1,1,1,3],[1,1,2,2],[1,1,2,3],
                                #    [1,1,3,3],[1,2,2,2],[1,2,2,3],[1,2,3,3],[1,3,3,3],
                                #    [2,2,2,2],[2,2,2,3],[2,2,3,3],[2,3,3,3],[3,3,3,3]]
a.repeated_combination(0).to_a  #=> [[]] # one combination of length 0
repeated_permutation(n) { |p| block } → ary Показать исходный код
repeated_permutation(n) → 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;
}

При вызове с блоком генерирует все повторяющиеся перестановки длины n элементов массива, а затем возвращает сам массив.

Реализация не гарантирует порядок, в котором генерируются повторяющиеся перестановки.

Если блок не задан, вместо него возвращается Enumerator.

Примеры:

a = [1, 2]
a.repeated_permutation(1).to_a  #=> [[1], [2]]
a.repeated_permutation(2).to_a  #=> [[1,1],[1,2],[2,1],[2,2]]
a.repeated_permutation(3).to_a  #=> [[1,1,1],[1,1,2],[1,2,1],[1,2,2],
                                #    [2,1,1],[2,1,2],[2,2,1],[2,2,2]]
a.repeated_permutation(0).to_a  #=> [[]] # one permutation of length 0
replace(other_ary) → ary Показать исходный код
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
    rb_ary_modify_check(copy);
    orig = to_ary(orig);
    if (copy == orig) return copy;

    if (RARRAY_LEN(orig) <= RARRAY_EMBED_LEN_MAX) {
        VALUE shared = 0;

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

Заменяет содержимое self содержимым other_ary, усекая или расширяя при необходимости.

a = [ "a", "b", "c", "d", "e" ]
a.replace([ "x", "y", "z" ])   #=> ["x", "y", "z"]
a                              #=> ["x", "y", "z"]
reverse → new_ary Показать исходный код
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;
}

Возвращает новый массив, содержащий элементы self в обратном порядке.

[ "a", "b", "c" ].reverse   #=> ["c", "b", "a"]
[ 1 ].reverse               #=> [1]
reverse! → ary Показать исходный код
static VALUE
rb_ary_reverse_bang(VALUE ary)
{
    return rb_ary_reverse(ary);
}

Обращает массив self на месте.

a = [ "a", "b", "c" ]
a.reverse!       #=> ["c", "b", "a"]
a                #=> ["c", "b", "a"]
reverse_each { |item| block } → ary Показать исходный код
reverse_each → 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;
}

Аналогично #each, но обходит self в обратном порядке.

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

выводит:

c b a
rindex(obj) → int or nil Показать исходный код
rindex { |item| block } → int or nil
rindex → Enumerator
static VALUE
rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
{
    const VALUE *ptr;
    VALUE val;
    long i = RARRAY_LEN(ary), len;

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

Возвращает индекс последнего объекта в self == до obj.

Если вместо аргумента задан блок, возвращает индекс первого объекта, для которого блок возвращает true, начиная с последнего объекта.

Возвращает nil если соответствия не найдено.

См. также #index.

Если ни блок, ни аргумент не заданы, возвращается Enumerator вместо этого.

a = [ "a", "b", "b", "b", "c" ]
a.rindex("b")             #=> 3
a.rindex("z")             #=> nil
a.rindex { |x| x == "b" } #=> 3
rotate(count=1) → new_ary Показать исходный код
static VALUE
rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE rotated;
    const VALUE *ptr;
    long len, cnt = 1;

    switch (argc) {
      case 1: cnt = NUM2LONG(argv[0]);
      case 0: break;
      default: rb_scan_args(argc, argv, "01", NULL);
    }

    len = RARRAY_LEN(ary);
    rotated = rb_ary_new2(len);
    if (len > 0) {
        cnt = rotate_count(cnt, len);
        ptr = RARRAY_CONST_PTR(ary);
        len -= cnt;
        ary_memcpy(rotated, 0, len, ptr + cnt);
        ary_memcpy(rotated, len, cnt, ptr);
    }
    ARY_SET_LEN(rotated, RARRAY_LEN(ary));
    return rotated;
}

Возвращает новый массив, вращая self так, чтобы элемент с count был первым элементом нового массива.

Если count отрицательное, то вращение происходит в противоположном направлении, начиная с конца self где -1 последний элемент.

a = [ "a", "b", "c", "d" ]
a.rotate         #=> ["b", "c", "d", "a"]
a                #=> ["a", "b", "c", "d"]
a.rotate(2)      #=> ["c", "d", "a", "b"]
a.rotate(-3)     #=> ["b", "c", "d", "a"]
rotate!(count=1) → ary Показать исходный код
static VALUE
rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
{
    long n = 1;

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

Вращает self на месте, так что элемент с count становится первым, и возвращает self.

Если count отрицательное, то вращение происходит в противоположном направлении, начиная с конца массива, где -1 последний элемент.

a = [ "a", "b", "c", "d" ]
a.rotate!        #=> ["b", "c", "d", "a"]
a                #=> ["b", "c", "d", "a"]
a.rotate!(2)     #=> ["d", "a", "b", "c"]
a.rotate!(-3)    #=> ["a", "b", "c", "d"]
sample → obj Показать исходный код
sample(random: rng) → obj
sample(n) → new_ary
sample(n, random: rng) → new_ary
static VALUE
rb_ary_sample(int argc, VALUE *argv, VALUE ary)
{
    VALUE nv, result;
    VALUE opts, randgen = rb_cRandom;
    long n, len, i, j, k, idx[10];
    long rnds[numberof(idx)];

    if (OPTHASH_GIVEN_P(opts)) {
        VALUE rnd;
        ID keyword_ids[1];

        keyword_ids[0] = id_random;
        rb_get_kwargs(opts, keyword_ids, 0, 1, &rnd);
        if (rnd != Qundef) {
            randgen = rnd;
        }
    }
    len = RARRAY_LEN(ary);
    if (argc == 0) {
        if (len < 2)
            i = 0;
        else
            i = RAND_UPTO(len);

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

    return result;
}

Выбирает случайный элемент или n случайных элементов из массива.

Элементы выбираются с помощью случайных и уникальных индексов в массиве, чтобы гарантировать, что элемент не повторяется, если только массив изначально не содержал дубликатов.

Если массив пуст, первая форма возвращает nil, а вторая форма возвращает пустой массив.

Необязательный аргумент rng будет использоваться в качестве генератора случайных чисел.

a = [ 1, 2, 3, 4, 5, 6, 7, 8, 9, 10 ]
a.sample         #=> 7
a.sample(4)      #=> [6, 4, 2, 5]
select { |item| block } → new_ary Показать исходный код
select → 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;
}

Возвращает новый массив, содержащий все элементы ary, для которых данный block возвращает значение истинности.

Если блок не задан, возвращается Enumerator.

[1,2,3,4,5].select { |num|  num.even?  }   #=> [2, 4]

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

См. также Enumerable#select.

select! {|item| block } → ary or nil Показать исходный код
select! → Enumerator
static VALUE
rb_ary_select_bang(VALUE ary)
{
    long i1, i2;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    rb_ary_modify(ary);
    for (i1 = i2 = 0; i1 < RARRAY_LEN(ary); i1++) {
        VALUE v = RARRAY_AREF(ary, i1);
        if (!RTEST(rb_yield(v))) continue;
        if (i1 != i2) {
            rb_ary_store(ary, i2, v);
        }
        i2++;
    }

    if (i1 == i2) return Qnil;
    if (i2 < i1)
        ARY_SET_LEN(ary, i2);
    return ary;
}

Вызывает заданный блок, передавая последовательные элементы из self, удаляя элементы, для которых блок возвращает false значение.

Если изменения были внесены, возвращается self, в противном случае возвращается nil.

См. также #keep_if

Если блок не задан, возвращается Enumerator.

shelljoin → строка Показать исходный код
# File lib/shellwords.rb, line 212
def shelljoin
  Shellwords.join(self)
end

Строит строку командной строки из списка аргументов array соединяя все элементы, экранированные для оболочки Bourne, и разделенные пробелом.

Подробности см. в Shellwords#shelljoin.

shift → обьект или nil Показать исходный код
shift(n) → новый_массив
static VALUE
rb_ary_shift_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE result;
    long n;

    if (argc == 0) {
        return rb_ary_shift(ary);
    }

    rb_ary_modify_check(ary);
    result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    n = RARRAY_LEN(result);
    if (ARY_SHARED_P(ary)) {
        if (ARY_SHARED_OCCUPIED(ARY_SHARED(ary))) {
            ary_mem_clear(ary, 0, n);
        }
        ARY_INCREASE_PTR(ary, n);
    }
    else {
        RARRAY_PTR_USE(ary, ptr, {
            MEMMOVE(ptr, ptr + n, VALUE, RARRAY_LEN(ary)-n);
        }); /* WB: no new reference */
    }
    ARY_INCREASE_LEN(ary, -n);

    return result;
}

Удаляет первый элемент из self и возвращает его (сдвигая все остальные элементы вниз на одну позицию). Возвращает nil если массив пуст.

Если задано число n, возвращает массив первых n элементов (или меньше), точно так же, как и array.slice!(0, n). С ary содержащим только оставшиеся элементы, не включая то, что было сдвинуто в new_ary. См. также #unshift для обратного эффекта.

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

args = [ "-m", "-q", "filename" ]
args.shift(2)  #=> ["-m", "-q"]
args           #=> ["filename"]
shuffle → новый_массив Показать исходный код
shuffle(random: rng) → новый_массив
static VALUE
rb_ary_shuffle(int argc, VALUE *argv, VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_shuffle_bang(argc, argv, ary);
    return ary;
}

Возвращает новый массив с перетасованными элементами self.

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

Опциональный аргумент rng будет использован в качестве генератора случайных чисел.

a.shuffle(random: Random.new(1))  #=> [1, 3, 2]
shuffle! → массив Показать исходный код
shuffle!(random: rng) → массив
static VALUE
rb_ary_shuffle_bang(int argc, VALUE *argv, VALUE ary)
{
    VALUE opts, randgen = rb_cRandom;
    long i, len;

    if (OPTHASH_GIVEN_P(opts)) {
        VALUE rnd;
        ID keyword_ids[1];

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

Перемешивает элементы в self на месте.

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

Опциональный аргумент rng будет использован в качестве генератора случайных чисел.

a.shuffle!(random: Random.new(1))  #=> [1, 3, 2]
размер()
Псевдоним для: длина
slice(индекс) → обьект или nil Показать исходный код
slice(начало, длина) → новый_массив или nil
slice(диапазон) → новый_массив или nil
VALUE
rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
    VALUE arg;
    long beg, len;

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

Ссылка на элемент — Возвращает элемент по index, или возвращает подмассив, начиная с start индекса и продолжающийся в течение length элементов, или возвращает подмассив, указанный range индексов.

Отрицательные индексы считаются от конца массива (‑1 — последний элемент). В случаях start и range начальный индекс находится перед элементом. Кроме того, возвращается пустой массив, когда начальный индекс диапазона элементов находится в конце массива.

Возвращает nil если индекс (или начальный индекс) находятся вне диапазона.

a = [ "a", "b", "c", "d", "e" ]
a[2] +  a[0] + a[1]    #=> "cab"
a[6]                   #=> nil
a[1, 2]                #=> [ "b", "c" ]
a[1..3]                #=> [ "b", "c", "d" ]
a[4..7]                #=> [ "e" ]
a[6..10]               #=> nil
a[-3, 3]               #=> [ "c", "d", "e" ]
# special cases
a[5]                   #=> nil
a[6, 1]                #=> nil
a[5, 1]                #=> []
a[5..10]               #=> []
slice!(индекс) → обьект или nil Показать исходный код
slice!(начало, длина) → новый_массив или nil
slice!(диапазон) → новый_массив или nil
static VALUE
rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg1, arg2;
    long pos, len, orig_len;

    rb_ary_modify_check(ary);
    if (argc == 2) {
        pos = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
      delete_pos_len:
        if (len < 0) return Qnil;
        orig_len = RARRAY_LEN(ary);
        if (pos < 0) {
            pos += orig_len;
            if (pos < 0) return Qnil;
        }
        else if (orig_len < pos) return Qnil;
        if (orig_len < pos + len) {
            len = orig_len - pos;
        }
        if (len == 0) return rb_ary_new2(0);
        arg2 = rb_ary_new4(len, RARRAY_CONST_PTR(ary)+pos);
        RBASIC_SET_CLASS(arg2, rb_obj_class(ary));
        rb_ary_splice(ary, pos, len, Qundef);
        return arg2;
    }

    if (argc != 1) {
        /* error report */
        rb_scan_args(argc, argv, "11", NULL, NULL);
    }
    arg1 = argv[0];

    if (!FIXNUM_P(arg1)) {
        switch (rb_range_beg_len(arg1, &pos, &len, RARRAY_LEN(ary), 0)) {
          case Qtrue:
            /* valid range */
            goto delete_pos_len;
          case Qnil:
            /* invalid range */
            return Qnil;
          default:
            /* not a range */
            break;
        }
    }

    return rb_ary_delete_at(ary, NUM2LONG(arg1));
}

Удаляет элемент(ы), заданные по index (до length элементов) или по range.

Возвращает удаленный объект (или объекты), или nil если index находится вне диапазона.

a = [ "a", "b", "c" ]
a.slice!(1)     #=> "b"
a               #=> ["a", "c"]
a.slice!(-1)    #=> "c"
a               #=> ["a"]
a.slice!(100)   #=> nil
a               #=> ["a"]
sort → новый_массив Показать исходный код
sort { |a, b| блок } → новый_массив
VALUE
rb_ary_sort(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_sort_bang(ary);
    return ary;
}

Возвращает новый массив, созданный путем сортировки self.

Сравнения для сортировки будут выполняться с использованием оператора <=> или с использованием опционального блока кода.

Блок должен реализовывать сравнение между a и b, и возвращать -1, когда a следует за b, 0 когда a и b эквивалентны, или +1 если b следует за a.

См. также Enumerable#sort_by.

a = [ "d", "a", "e", "c", "b" ]
a.sort                    #=> ["a", "b", "c", "d", "e"]
a.sort { |x,y| y <=> x }  #=> ["e", "d", "c", "b", "a"]
sort! → массив Показать исходный код
sort! { |a, b| блок } → массив
VALUE
rb_ary_sort_bang(VALUE ary)
{
    rb_ary_modify(ary);
    assert(!ARY_SHARED_P(ary));
    if (RARRAY_LEN(ary) > 1) {
        VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
        struct ary_sort_data data;
        long len = RARRAY_LEN(ary);

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

Сортирует self на месте.

Сравнения для сортировки будут выполняться с использованием оператора <=> или с использованием опционального блока кода.

Блок должен реализовывать сравнение между a и b, и возвращать -1, когда a следует за b, 0 когда a и b эквивалентны, или +1 если b следует за a.

См. также Enumerable#sort_by.

a = [ "d", "a", "e", "c", "b" ]
a.sort!                    #=> ["a", "b", "c", "d", "e"]
a.sort! { |x,y| y <=> x }  #=> ["e", "d", "c", "b", "a"]
sort_by! { |obj| блок } → массив Показать исходный код
sort_by! → 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;
}

Сортирует self на месте, используя набор ключей, сгенерированных путем отображения значений в self через заданный блок.

Если блок не задан, вместо него возвращается Enumerator.

take(n) → новый_массив Показать исходный код
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);
}

Возвращает первые n элементы из массива.

Если задано отрицательное число, генерируется исключение ArgumentError.

См. также #drop

a = [1, 2, 3, 4, 5, 0]
a.take(3)             #=> [1, 2, 3]
take_while { |arr| блок } → новый_массив Показать исходный код
take_while → Enumerator
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));
}

Передает элементы в блок, пока блок не вернет nil или false, затем останавливает итерацию и возвращает массив всех предыдущих элементов.

Если блок не задан, вместо него возвращается Enumerator.

См. также #drop_while

a = [1, 2, 3, 4, 5, 0]
a.take_while { |i| i < 3 }  #=> [1, 2]
to_a → массив Показать исходный код
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;
}

Возвращает self.

Если вызывается на подклассе Array, преобразует получателя в объект Array.

to_ary → массив Показать исходный код
static VALUE
rb_ary_to_ary_m(VALUE ary)
{
    return ary;
}

Возвращает self.

to_h → хеш Показать исходный код
static VALUE
rb_ary_to_h(VALUE ary)
{
    long i;
    VALUE hash = rb_hash_new();
    for (i=0; i<RARRAY_LEN(ary); i++) {
        VALUE key_value_pair = rb_check_array_type(rb_ary_elt(ary, i));
        if (NIL_P(key_value_pair)) {
            rb_raise(rb_eTypeError, "wrong element type %s at %ld (expected array)",
                rb_builtin_class_name(rb_ary_elt(ary, i)), 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;
}

Возвращает результат интерпретации ary как массива [key, value] пар.

[[:foo, :bar], [1, 2]].to_h
  # => {:foo => :bar, 1 => 2}
to_s()
Псевдоним для: inspect
transpose → новый_массив Показать исходный код
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;
}

Предполагает, что self представляет собой массив массивов и транспонирует строки и столбцы.

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

Если длина подмассивов не совпадает, генерируется исключение IndexError.

END_OF_DOCUMENT_MARKER
uniq → new_ary Показать исходный код
uniq { |item| ... } → new_ary
static VALUE
rb_ary_uniq(VALUE ary)
{
    VALUE hash, uniq;

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

    return uniq;
}

Возвращает новый массив, удаляя дублирующиеся значения в self.

Если задан блок, он будет использовать возвращаемое значение блока для сравнения.

Для повышения эффективности сравнение значений выполняется с помощью методов hash и eql?.

a = [ "a", "a", "b", "b", "c" ]
a.uniq   # => ["a", "b", "c"]

b = [["student","sam"], ["student","george"], ["teacher","matz"]]
b.uniq { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
uniq! → ary or nil Показать исходный код
uniq! { |item| ... } → ary or 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) && !ARY_EMBED_P(ary)) {
        rb_ary_unshare(ary);
        FL_SET_EMBED(ary);
    }
    ary_resize_capa(ary, hash_size);
    st_foreach(rb_hash_tbl_raw(hash), push_value, ary);
    ary_recycle_hash(hash);

    return ary;
}

Удаляет дублирующие элементы из self.

Если задан блок, он будет использовать возвращаемое значение блока для сравнения.

Для повышения эффективности сравнение значений выполняется с помощью методов hash и eql?.

Возвращает nil в случае, если изменения не были внесены (то есть, дубликаты не найдены).

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

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

c = [["student","sam"], ["student","george"], ["teacher","matz"]]
c.uniq! { |s| s.first } # => [["student", "sam"], ["teacher", "matz"]]
unshift(obj, ...) → ary Показать исходный код
static VALUE
rb_ary_unshift_m(int argc, VALUE *argv, VALUE ary)
{
    long len = RARRAY_LEN(ary);
    VALUE target_ary;

    if (argc == 0) {
        rb_ary_modify_check(ary);
        return ary;
    }

    target_ary = ary_ensure_room_for_unshift(ary, argc);
    ary_memcpy0(ary, 0, argc, argv, target_ary);
    ARY_SET_LEN(ary, len + argc);
    return ary;
}

Добавляет объекты в начало self, перемещая другие элементы вверх. См. также #shift для обратного эффекта.

a = [ "b", "c", "d" ]
a.unshift("a")   #=> ["a", "b", "c", "d"]
a.unshift(1, 2)  #=> [ 1, 2, "a", "b", "c", "d"]
values_at(selector, ...) → new_ary Показать исходный код
static VALUE
rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
{
    return rb_get_values_at(ary, RARRAY_LEN(ary), argc, argv, rb_ary_entry);
}

Возвращает массив, содержащий элементы в self, соответствующие заданным selector.

Селекторы могут быть целыми индексами или диапазонами.

См. также #select.

a = %w{ a b c d e f }
a.values_at(1, 3, 5)          # => ["b", "d", "f"]
a.values_at(1, 3, 5, 7)       # => ["b", "d", "f", nil]
a.values_at(-1, -2, -2, -7)   # => ["f", "e", "e", nil]
a.values_at(4..6, 3...6)      # => ["e", "f", nil, "d", "e", "f"]
zip(arg, ...) → new_ary Показать исходный код
zip(arg, ...) { |arr| block } → nil
static VALUE
rb_ary_zip(int argc, VALUE *argv, VALUE ary)
{
    int i, j;
    long len = RARRAY_LEN(ary);
    VALUE result = Qnil;

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

    if (rb_block_given_p()) {
        int arity = rb_block_arity();

        if (arity > 1) {
            VALUE work, *tmp;

            tmp = ALLOCV_N(VALUE, work, argc+1);

            for (i=0; i<RARRAY_LEN(ary); i++) {
                tmp[0] = RARRAY_AREF(ary, i);
                for (j=0; j<argc; j++) {
                    tmp[j+1] = rb_ary_elt(argv[j], i);
                }
                rb_yield_values2(argc+1, tmp);
            }

            if (work) ALLOCV_END(work);
        }
        else {
            for (i=0; i<RARRAY_LEN(ary); i++) {
                VALUE tmp = rb_ary_new2(argc+1);

                rb_ary_push(tmp, RARRAY_AREF(ary, i));
                for (j=0; j<argc; j++) {
                    rb_ary_push(tmp, rb_ary_elt(argv[j], i));
                }
                rb_yield(tmp);
            }
        }
    }
    else {
        result = rb_ary_new_capa(len);

        for (i=0; i<len; i++) {
            VALUE tmp = rb_ary_new_capa(argc+1);

            rb_ary_push(tmp, RARRAY_AREF(ary, i));
            for (j=0; j<argc; j++) {
                rb_ary_push(tmp, rb_ary_elt(argv[j], i));
            }
            rb_ary_push(result, tmp);
        }
    }

    return result;
}

Преобразует любые аргументы в массивы, затем объединяет элементы self с соответствующими элементами каждого аргумента.

Это генерирует последовательность ary.size массивов по n элементов, где n — на единицу больше количества аргументов.

Если размер любого аргумента меньше размера исходного массива, используются значения nil.

Если задан блок, он вызывается для каждого выходного array , в противном случае возвращается массив массивов.

a = [ 4, 5, 6 ]
b = [ 7, 8, 9 ]
[1, 2, 3].zip(a, b)   #=> [[1, 4, 7], [2, 5, 8], [3, 6, 9]]
[1, 2].zip(a, b)      #=> [[1, 4, 7], [2, 5, 8]]
a.zip([1, 2], [8])    #=> [[4, 1, 8], [5, 2, nil], [6, nil, nil]]
ary | other_ary → new_ary Показать исходный код
static VALUE
rb_ary_or(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3;
    long i;

    ary2 = to_ary(ary2);
    hash = ary_make_hash(ary1);

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

Объединение множеств — Возвращает новый массив, объединяя ary с other_ary, исключая дубликаты и сохраняя порядок из исходного массива.

Для повышения эффективности сравнение элементов выполняется с помощью методов hash и eql?.

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

См. также #uniq.

Ruby Core © 1993–2017 Yukihiro Matsumoto
Licensed under the Ruby License.
Ruby Standard Library © contributors
Licensed under their own licenses.

Spec-Zone.ru

Настройки Оффлайн Что нового Помощь О нас
Spec-Zone .ru
спецификации, руководства, описания, API