Spec-Zone.ru › Ruby 3.4

класс Array

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

Объект Array представляет собой упорядоченную коллекцию объектов, индексированных целыми числами, называемых элементами; он представляет собой структуру данных «массив».

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

К важным структурам данных, использующим массивы, относятся:

  • Вектор координат.

  • Матрица.

  • Куча.

  • Хеш-таблица.

  • Двустороннюю очередь (deque).

  • Очередь.

  • Стек.

Также существуют структуры данных, похожие на массивы:

  • Ассоциативный массив (см. Hash).

  • Директория (см. Dir).

  • Переменная окружения (см. ENV).

  • Множество (см. Set).

  • Строка (см. String).

Индексы массива

Индексация массивов начинается с 0, как в C или Java.

Положительный индекс — это смещение от первого элемента:

  • Индекс 0 указывает на первый элемент.

  • Индекс 1 указывает на второй элемент.

  • …

Отрицательный индекс — это смещение назад от конца массива:

  • Индекс -1 указывает на последний элемент.

  • Индекс -2 указывает на предпоследний элемент.

  • …

Индексы в диапазоне и вне диапазона

Положительный индекс находится в диапазоне тогда и только тогда, когда он меньше размера массива. Для массива из 3 элементов:

  • Индексы от 0 до 2 находятся в диапазоне.

  • Индекс 3 находится вне диапазона.

Отрицательный индекс находится в диапазоне тогда и только тогда, когда его абсолютное значение не больше размера массива. Для массива из 3 элементов:

  • Индексы от -1 до -3 находятся в диапазоне.

  • Индекс -4 находится вне диапазона.

Эффективный индекс

Хотя эффективный индекс массива всегда является целым числом, некоторые методы (как внутри класса Array, так и в других местах) принимают один или несколько нецелых аргументов, которые являются объектами, преобразуемыми в целые числа.

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

Вы можете явно создать объект Array с помощью:

  • Литерала массива:

    [1, 'one', :one, [2, 'two', :two]]
    
  • Литерала массива строк %w или %W:

    %w[foo bar baz] # => ["foo", "bar", "baz"]
    %w[1 % *]       # => ["1", "%", "*"]
    
  • Литерала массива символов %i или %I:

    %i[foo bar baz] # => [:foo, :bar, :baz]
    %i[1 % *]       # => [:"1", :%, :*]
    
  • Метода Kernel#Array:

    Array(["a", "b"])             # => ["a", "b"]
    Array(1..5)                   # => [1, 2, 3, 4, 5]
    Array(key: :value)            # => [[:key, :value]]
    Array(nil)                    # => []
    Array(1)                      # => [1]
    Array({:a => "a", :b => "b"}) # => [[:a, "a"], [:b, "b"]]
    
  • Метода Array.new:

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

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

    Другой способ создания массива с различными объектами, используя блок; это использование безопасно для изменяемых объектов, таких как хэши, строки или другие массивы:

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

    Вот способ создания многомерного массива:

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

Некоторые методы Ruby, как в ядре, так и в стандартной библиотеке, предоставляют метод экземпляра to_a, который преобразует объект в массив.

  • ARGF#to_a

  • Array#to_a

  • Enumerable#to_a

  • Hash#to_a

  • MatchData#to_a

  • NilClass#to_a

  • OptionParser#to_a

  • Range#to_a

  • Set#to_a

  • Struct#to_a

  • Time#to_a

  • Benchmark::Tms#to_a

  • CSV::Table#to_a

  • Enumerator::Lazy#to_a

  • Gem::List#to_a

  • Gem::NameTuple#to_a

  • Gem::Platform#to_a

  • Gem::RequestSet::Lockfile::Tokenizer#to_a

  • Gem::SourceList#to_a

  • OpenSSL::X509::Extension#to_a

  • OpenSSL::X509::Name#to_a

  • Racc::ISet#to_a

  • Rinda::RingFinger#to_a

  • Ripper::Lexer::Elem#to_a

  • RubyVM::InstructionSequence#to_a

  • YAML::DBM#to_a

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

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

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

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

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

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

Другой способ доступа к элементу массива — использование метода at.

arr.at(0) #=> 1

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

Чтобы вызвать ошибку для индексов за пределами границ массива или предоставить значение по умолчанию в этом случае, вы можете использовать fetch.

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

Специальные методы 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]

Получение информации об Array

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

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

Метод pop удаляет последний элемент массива и возвращает его:

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

Чтобы получить и одновременно удалить первый элемент, используйте shift:

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

Чтобы удалить элемент по определенному индексу:

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

Чтобы удалить определенный элемент в любом месте массива, используйте delete:

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

Полезный метод, если вам нужно удалить nil значения из массива, — compact:

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

Ещё одна распространённая потребность — удаление повторяющихся элементов из массива.

Он имеет неразрушающий метод uniq и разрушающий метод uniq!

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

Итерация по массивам

Как и все классы, включающие модуль Enumerable, класс Array имеет метод each, который определяет, какие элементы нужно итерировать и как. В случае метода each класса Array все элементы экземпляра Array передаются предоставленному блоку последовательно.

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

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

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

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

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

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

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

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

Не-деструктивный выбор

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

Деструктивный выбор

select! и reject! — соответствующие деструктивные методы для 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]

Что здесь

Во-первых, что где-то ещё. Класс Array:

  • Наследуется от класса Object.

  • Включает модуль Enumerable, который предоставляет десятки дополнительных методов.

Здесь класс Array предоставляет методы, полезные для:

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

  • Запросы

  • Сравнение

  • Получение

  • Присваивание

  • Удаление

  • Объединение

  • Итерация

  • Преобразование

  • И многое другое…

Методы для создания Array

  • ::[]: Возвращает новый массив, заполненный заданными объектами.

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

  • ::try_convert: Возвращает новый массив, созданный из заданного объекта.

См. также Создание массивов.

Методы для запросов

  • all?: Возвращает, удовлетворяют ли все элементы заданному критерию.

  • any?: Возвращает, удовлетворяет ли хотя бы один элемент заданному критерию.

  • count: Возвращает количество элементов, удовлетворяющих заданному критерию.

  • empty?: Возвращает, пуст ли массив.

  • find_index (псевдоним index): Возвращает индекс первого элемента, удовлетворяющего заданному критерию.

  • hash: Возвращает целочисленный код хэша.

  • include?: Возвращает, содержит ли массив заданный объект.

  • length (псевдоним size): Возвращает количество элементов.

  • none?: Возвращает, не содержит ли массив заданный объект.

  • one?: Возвращает, содержит ли массив ровно один заданный объект.

  • rindex: Возвращает индекс последнего элемента, удовлетворяющего заданному критерию.

Методы для сравнения

  • <=>: Возвращает -1, 0 или 1, в зависимости от того, меньше, равен или больше заданный объект.

  • ==: Возвращает, равны ли соответствующие элементы в массиве и заданном объекте.

  • eql?: Возвращает, равны ли соответствующие элементы в массиве и заданном объекте.

Методы для получения

Эти методы не изменяют self.

  • [] (псевдоним slice): Возвращает последовательные элементы, определяемые заданным аргументом.

  • assoc: Возвращает первый элемент, который является массивом, первый элемент которого равен заданному объекту.

  • at: Возвращает элемент по заданному смещению.

  • bsearch: Возвращает элемент, выбранный с помощью бинарного поиска, определяемого заданным блоком.

  • bsearch_index: Возвращает индекс элемента, выбранного с помощью бинарного поиска, определяемого заданным блоком.

  • compact: Возвращает массив, содержащий все не-nil элементы.

  • dig: Возвращает объект вложенных объектов, определяемый заданным индексом и дополнительными аргументами.

  • drop: Возвращает хвостовые элементы, определяемые заданным индексом.

  • drop_while: Возвращает хвостовые элементы, определяемые заданным блоком.

  • fetch: Возвращает элемент по заданному смещению.

  • fetch_values: Возвращает элементы по заданным смещениям.

  • first: Возвращает один или несколько ведущих элементов.

  • last: Возвращает один или несколько хвостовых элементов.

  • max: Возвращает один или несколько элементов с максимальным значением, как определено <=> или заданным блоком.

  • min: Возвращает один или несколько элементов с минимальным значением, как определено <=> или заданным блоком.

  • minmax: Возвращает элементы с минимальным и максимальным значением, как определено <=> или заданным блоком.

  • rassoc: Возвращает первый элемент, который является массивом, второй элемент которого равен заданному объекту.

  • reject: Возвращает массив, содержащий элементы, не отклоненные заданным блоком.

  • reverse: Возвращает все элементы в обратном порядке.

  • rotate: Возвращает все элементы с некоторыми элементами, повернутыми с одного конца на другой.

  • sample: Возвращает один или несколько случайных элементов.

  • select (псевдоним filter): Возвращает массив, содержащий элементы, выбранные заданным блоком.

  • shuffle: Возвращает элементы в случайном порядке.

  • sort: Возвращает все элементы в порядке, определённом <=> или заданным блоком.

  • take: Возвращает ведущие элементы, определяемые заданным индексом.

  • take_while: Возвращает ведущие элементы, определяемые заданным блоком.

  • uniq: Возвращает массив, содержащий уникальные элементы.

  • values_at: Возвращает элементы по заданным смещениям.

Методы для присваивания

Эти методы добавляют, заменяют или переупорядочивают элементы в self.

  • <<: Добавляет элемент.

  • []=: Присваивает указанные элементы заданному объекту.

  • concat: Добавляет все элементы из заданных массивов.

  • fill: Заменяет указанные элементы заданными объектами.

  • flatten!: Заменяет каждый вложенный массив в self элементами из этого массива.

  • initialize_copy (алиас replace): Заменяет содержимое self содержимым заданного массива.

  • insert: Вставляет заданные объекты в заданный смещение; не заменяет элементы.

  • push (алиас append): Добавляет элементы.

  • reverse!: Заменяет self своими элементами в обратном порядке.

  • rotate!: Заменяет self своими элементами, повернутыми.

  • shuffle!: Заменяет self своими элементами в случайном порядке.

  • sort!: Заменяет self своими отсортированными элементами, как определено <=> или заданным блоком.

  • sort_by!: Заменяет self своими элементами, отсортированными, как определено заданным блоком.

  • unshift (алиас prepend): Добавляет ведущие элементы в начало.

Методы для удаления

Каждый из этих методов удаляет элементы из self:

  • clear: Удаляет все элементы.

  • compact!: Удаляет все nil элементы.

  • delete: Удаляет элементы, равные заданному объекту.

  • delete_at: Удаляет элемент по заданному смещению.

  • delete_if: Удаляет элементы, заданные заданным блоком.

  • keep_if: Удаляет элементы, не заданные заданным блоком.

  • pop: Удаляет и возвращает последний элемент.

  • reject!: Удаляет элементы, заданные заданным блоком.

  • select! (алиас filter!): Удаляет элементы, не заданные заданным блоком.

  • shift: Удаляет и возвращает первый элемент.

  • slice!: Удаляет и возвращает последовательность элементов.

  • uniq!: Удаляет дубликаты.

Методы для объединения

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

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

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

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

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

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

  • product: Возвращает или генерирует все комбинации элементов из self и заданных массивов.

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

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

Методы для итерации

  • combination: Вызывает заданный блок с комбинациями элементов из self; комбинация не использует один и тот же элемент более одного раза.

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

  • each: Передает каждый элемент заданному блоку.

  • each_index: Передает индекс каждого элемента заданному блоку.

  • permutation: Вызывает заданный блок с перестановками элементов из self; перестановка не использует один и тот же элемент более одного раза.

  • repeated_combination: Вызывает заданный блок с комбинациями элементов из self; в комбинации может использоваться один и тот же элемент более одного раза.

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

  • reverse_each: Передает каждый элемент в обратном порядке заданному блоку.

Методы для преобразования

  • collect (алиас map): Возвращает массив, содержащий возвращаемое значение блока для каждого элемента.

  • collect! (алиас map!): Заменяет каждый элемент возвращаемым значением блока.

  • flatten: Возвращает массив, являющийся рекурсивным разложением self.

  • inspect (алиас to_s): Возвращает новую String, содержащую элементы.

  • join: Возвращает новую строку, содержащую элементы, объединенные с использованием разделителя поля.

  • to_a: Возвращает self или новый массив, содержащий все элементы.

  • to_ary: Возвращает self.

  • to_h: Возвращает новый хеш, сформированный из элементов.

  • transpose: Транспонирует self, который должен быть массивом массивов.

  • zip: Возвращает новый массив массивов, содержащий self и заданные массивы.

Другие методы

  • *: Возвращает одно из следующего:

    • С целочисленным аргументом n, новый массив, который является конкатенацией n копий self.

    • Со строковым аргументом field_separator, новую строку, эквивалентную join(field_separator).

  • pack: Упаковывает элементы в двоичную последовательность.

  • sum: Возвращает сумму элементов, в соответствии с + или заданным блоком.

Методы класса

[] (*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[]                # => []
Array.[](1, 'a', /^A/) # => [1, "a", /^A/]

См. также: Методы для создания массива.

new → new_empty_array
new(array) → new_array
new(size, default_value = nil) → new_array
new(size = 0) {|index| ... } → new_array
Исходный код
static VALUE
rb_ary_initialize(int argc, VALUE *argv, VALUE ary)
{
    long len;
    VALUE size, val;

    rb_ary_modify(ary);
    if (argc == 0) {
        rb_ary_reset(ary);
        RUBY_ASSERT(ARY_EMBED_P(ary));
        RUBY_ASSERT(ARY_EMBED_LEN(ary) == 0);
        if (rb_block_given_p()) {
            rb_warning("given block not used");
        }
        return ary;
    }
    rb_scan_args(argc, argv, "02", &size, &val);
    if (argc == 1 && !FIXNUM_P(size)) {
        val = rb_check_array_type(size);
        if (!NIL_P(val)) {
            rb_ary_replace(ary, val);
            return ary;
        }
    }

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

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

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

Без блока и без аргументов возвращает новый пустой массив:

Array.new # => []

Без блока и с аргументом-массивом возвращает новый массив с теми же элементами:

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

Без блока и с целым числом в качестве аргумента возвращает новый массив, содержащий указанное количество экземпляров данного default_value:

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

С блоком возвращает массив заданных size; вызывает блок для каждого index в диапазоне (0...size); элементом в возвращаемом массиве по этому index является возвращаемое значение блока:

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

Распространённая ошибка начинающих программистов на Ruby — передача выражения в качестве default_value:

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

Если вы хотите, чтобы элементы массива были уникальными, вы должны передать блок:

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

Вызывает исключение TypeError, если первый аргумент не является массивом или объектом, преобразуемым в целое число. Вызывает исключение ArgumentError, если первый аргумент — отрицательное целое число.

См. также: Методы для создания массива.

try_convert(object) → object, new_array, or nil
Исходный код
static VALUE
rb_ary_s_try_convert(VALUE dummy, VALUE ary)
{
    return rb_check_array_type(ary);
}

Попытка вернуть массив, исходя из данного object.

Если object является массивом, возвращает object.

В противном случае, если object отвечает на :to_ary, вызывается object.to_ary: если возвращаемое значение является массивом или nil, возвращается это значение; в противном случае, выбрасывается исключение TypeError.

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

См. также: Методы для создания массива.

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

self & other_array → new_array
Исходный код
static VALUE
rb_ary_and(VALUE ary1, VALUE ary2)
{
    VALUE hash, ary3, v;
    st_data_t vv;
    long i;

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

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

    hash = ary_make_hash(ary2);

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

    return ary3;
}

Возвращает новый массив, содержащий пересечение self и other_array; то есть, содержащий те элементы, которые присутствуют как в self, так и в other_array;

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

Опускает дубликаты:

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

Сохраняет порядок из self;

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

Определяет общие элементы, используя метод eql? (как определено для каждого элемента в self).

См. также: Методы для объединения.

self * n → new_array
self * string_separator → 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_cArray, 0);
        goto out;
    }
    if (len < 0) {
        rb_raise(rb_eArgError, "negative argument");
    }
    if (ARY_MAX_SIZE/len < RARRAY_LEN(ary)) {
        rb_raise(rb_eArgError, "argument too big");
    }
    len *= RARRAY_LEN(ary);

    ary2 = ary_new(rb_cArray, len);
    ARY_SET_LEN(ary2, len);

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

При положительном целочисленном аргументе n, возвращает новый массив, созданный путём конкатенации n копий self:

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

При строковом аргументе string_separator, эквивалентно self.join(string_separator):

[0, [0, 1], {foo: 0}] * ', ' # => "0, 0, 1, {foo: 0}"
self + other_array → new_array
Исходный код
VALUE
rb_ary_plus(VALUE x, VALUE y)
{
    VALUE z;
    long len, xlen, ylen;

    y = to_ary(y);
    xlen = RARRAY_LEN(x);
    ylen = RARRAY_LEN(y);
    len = xlen + ylen;
    z = rb_ary_new2(len);

    ary_memcpy(z, 0, xlen, RARRAY_CONST_PTR(x));
    ary_memcpy(z, xlen, ylen, RARRAY_CONST_PTR(y));
    ARY_SET_LEN(z, len);
    return z;
}

Возвращает новый массив, содержащий все элементы self, после которых следуют все элементы other_array:

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

См. также: Методы для объединения.

self - other_array → new_array
Исходный код
VALUE
rb_ary_diff(VALUE ary1, VALUE ary2)
{
    VALUE ary3;
    VALUE hash;
    long i;

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

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

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

    return ary3;
}

Возвращает новый массив, содержащий только те элементы из self, которые не найдены в other_array; порядок из self сохраняется:

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

Элементы сравниваются с использованием метода eql? (как определено для каждого элемента в self).

См. также: Методы для объединения.

self << object → self
Исходный код
VALUE
rb_ary_push(VALUE ary, VALUE item)
{
    long idx = RARRAY_LEN((ary_verify(ary), ary));
    VALUE target_ary = ary_ensure_room_for_push(ary, 1);
    RARRAY_PTR_USE(ary, ptr, {
        RB_OBJ_WRITE(target_ary, &ptr[idx], item);
    });
    ARY_SET_LEN(ary, idx + 1);
    ary_verify(ary);
    return ary;
}

Добавляет object в качестве последнего элемента в self; возвращает self:

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

Добавляет object как отдельный элемент, даже если это другой массив:

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

См. также: Методы присваивания.

self <=> other_array → -1, 0, or 1
Исходный код
VALUE
rb_ary_cmp(VALUE ary1, VALUE ary2)
{
    long len;
    VALUE v;

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

Возвращает -1, 0 или 1, в зависимости от того, меньше, равно или больше self чем other_array.

Итерируется по каждому индексу i в (0...self.size):

  • Вычисляет result[i] как self[i] <=> other_array[i].

  • Немедленно возвращает 1, если result[i] равно 1:

    [0, 1, 2] <=> [0, 0, 2] # => 1
    
  • Немедленно возвращает -1, если result[i] равно -1:

    [0, 1, 2] <=> [0, 2, 2] # => -1
    
  • Продолжает, если result[i] равно 0.

Если все result равны 0, возвращает self.size <=> other_array.size (см. Integer#<=>):

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

Обратите внимание, что когда other_array больше чем self, его хвостовые элементы не влияют на результат:

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

См. также: Методы сравнения.

self == other_array → true or false
Исходный код
static VALUE
rb_ary_equal(VALUE ary1, VALUE ary2)
{
    if (ary1 == ary2) return Qtrue;
    if (!RB_TYPE_P(ary2, T_ARRAY)) {
        if (!rb_respond_to(ary2, idTo_ary)) {
            return Qfalse;
        }
        return rb_equal(ary2, ary1);
    }
    if (RARRAY_LEN(ary1) != RARRAY_LEN(ary2)) return Qfalse;
    if (RARRAY_CONST_PTR(ary1) == RARRAY_CONST_PTR(ary2)) return Qtrue;
    return rb_exec_recursive_paired(recursive_equal, ary1, ary2, ary2);
}

Возвращает значение true, если:

  • self и other_array имеют одинаковый размер.

  • Их соответствующие элементы совпадают; то есть, для каждого индекса i в (0...self.size), self[i] == other_array[i].

Примеры:

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

Этот метод отличается от метода Array#eql?, который сравнивает элементы, используя Object#eql?.

См. также: Методы сравнения.

self[index] → object or nil
self[start, length] → object or nil
self[range] → object or nil
self[aseq] → object or nil
Исходный код
VALUE
rb_ary_aref(int argc, const VALUE *argv, VALUE ary)
{
    rb_check_arity(argc, 1, 2);
    if (argc == 2) {
        return rb_ary_aref2(ary, argv[0], argv[1]);
    }
    return rb_ary_aref1(ary, argv[0]);
}

Возвращает элементы из self; не изменяет self.

Кратко:

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

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

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

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

При целочисленном аргументе index возвращает элемент по смещению index:

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

Если index отрицательное, считает от конца self:

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

Если index вне диапазона, возвращает nil.

При двух целочисленных аргументах start и length возвращает новый массив размера length, содержащий последовательные элементы, начиная со смещения start:

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

Если start + length больше self.length, возвращает все элементы от смещения start до конца:

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

Если start == self.size и length >= 0, возвращает пустой массив.

Если length отрицательное, возвращает nil.

При одиночном аргументе типа диапазон range рассматривает range.min как начальный индекс, а range.size как конечный:

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

Особый случай: если range.start == a.size, возвращает пустой массив.

Если range.end отрицательное, вычисляет конечный индекс с конца:

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

Если range.start отрицательное, вычисляет начальный индекс с конца:

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

Если range.start больше размера массива, возвращает nil.

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

При одиночном аргументе типа арифметической последовательности aseq возвращает массив элементов, соответствующих индексам, полученным из последовательности.

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

В отличие от среза с диапазоном, если начало или конец арифметической последовательности больше размера массива, выбрасывает RangeError.

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

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

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

См. также: Методы извлечения.

Также известен как: slice
END_OF_DOCUMENT_MARKER
self[index] = object → object
self[start, length] = object → object
self[range] = object → object
Исходный код
static VALUE
rb_ary_aset(int argc, VALUE *argv, VALUE ary)
{
    long offset, beg, len;

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

    offset = NUM2LONG(argv[0]);
    return ary_aset_by_rb_ary_store(ary, offset, argv[1]);
}

Присваивает элементы в self, на основе заданного object; возвращает object.

Кратко:

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

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

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

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

При передаче аргумента Integer index присваивает object элементу в self.

Если index неотрицательно, присваивает object элемент с смещением index:

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

Если index больше self.length, расширяет массив:

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

Если index отрицательно, считает назад от конца массива:

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

При передаче аргументов Integer start и length и object не является Array, удаляет length - 1 элементов, начиная со смещения start, и присваивает object со смещением start:

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

Если start отрицательно, считает назад от конца массива:

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

Если start неотрицательно и выходит за пределы массива ( >= self.size), расширяет массив на nil, присваивает object со смещением start, и игнорирует length:

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

Если length равно нулю, сдвигает элементы, начиная со смещения start, и присваивает object со смещением start:

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

Если length слишком велико для существующего массива, массив не расширяется:

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

При передаче аргумента Range range и object не является Array, удаляет length - 1 элементов, начиная со смещения start, и присваивает object со смещением start:

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

если range.begin отрицательно, считает назад от конца массива:

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

Если длина массива меньше range.begin, расширяет массив на nil, присваивает object со смещением range.begin, и игнорирует length:

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

Если range.end равно нулю, сдвигает элементы, начиная со смещения start, и присваивает object со смещением start:

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

Если range.end отрицательно, присваивает object со смещением start, сохраняет range.end.abs -1 элементов после него и удаляет те, что за пределами:

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

Если range.end слишком велико для существующего массива, заменяет элементы массива, но не расширяет массив значениями nil:

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

См. также: Методы присваивания.

self | other_array → new_array
Исходный код
static VALUE
rb_ary_or(VALUE ary1, VALUE ary2)
{
    VALUE hash;

    ary2 = to_ary(ary2);
    if (RARRAY_LEN(ary1) + RARRAY_LEN(ary2) <= SMALL_ARRAY_LEN) {
        VALUE ary3 = rb_ary_new();
        rb_ary_union(ary3, ary1);
        rb_ary_union(ary3, ary2);
        return ary3;
    }

    hash = ary_make_hash(ary1);
    rb_ary_union_hash(hash, ary2);

    return rb_hash_values(hash);
}

Возвращает объединение self и other_array; дубликаты удаляются; порядок сохраняется; элементы сравниваются с помощью eql?:

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

См. также: Методы объединения.

all? → true or false
all?(object) → true or false
all? {|element| ... } → true or false
Исходный код
static VALUE
rb_ary_all_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);

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

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

Без блока и аргументов, возвращает true, если все элементы self истинны:

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

С аргументом object возвращает true, если object === ele для каждого элемента ele в self:

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

С блоком, вызывает блок с каждым элементом в self; возвращает true, если блок возвращает только истинные значения:

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

С блоком и аргументом object, игнорирует блок и использует object как описано выше.

Особый случай: возвращает true если self пусто (независимо от переданных аргументов или блока).

См. также: Методы запросов.

any? → true or false
any?(object) → true or false
any? {|element| ... } → true or false
Исходный код
static VALUE
rb_ary_any_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);

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

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

Без блока и аргументов, возвращает true, если любой элемент self истинен:

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

С аргументом object возвращает true, если object === ele для любого элемента ele в self:

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

С блоком, вызывает блок с каждым элементом в self; возвращает true, если блок возвращает любое истинное значение:

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

С блоком и аргументом object, игнорирует блок и использует object как описано выше.

Особый случай: возвращает false если self пусто (независимо от переданных аргументов или блока).

См. также: Методы запросов.

append(*objects) → self

Добавляет каждый аргумент в objects в self; возвращает self:

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

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

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

См. также: Методы присваивания.

Псевдоним для: push
assoc(object) → found_array 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;
}

Возвращает первый элемент ele в self такой, что ele является массивом и ele[0] == object:

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

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

См. также: Array#rassoc; также см. Методы извлечения.

at(index) → object or nil
Исходный код
VALUE
rb_ary_at(VALUE ary, VALUE pos)
{
    return rb_ary_entry(ary, NUM2LONG(pos));
}

Возвращает элемент self по заданному index или nil если такого элемента нет; index должен быть объектом, преобразуемым в целое число.

Для неотрицательного index, возвращает элемент self со смещением index:

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

Для отрицательного index, считает назад от конца self:

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

См. также: Array#[]; также см. Методы извлечения.

bsearch {|element| ... } → found_element or nil
bsearch → new_enumerator
Source
static VALUE
rb_ary_bsearch(VALUE ary)
{
    VALUE index_result = rb_ary_bsearch_index(ary);

    if (FIXNUM_P(index_result)) {
        return rb_ary_entry(ary, FIX2LONG(index_result));
    }
    return index_result;
}

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

См. Binary Searching.

Связанное: см. Methods for Fetching.

bsearch_index {|element| ... } → integer or nil
bsearch_index → new_enumerator
Source
static VALUE
rb_ary_bsearch_index(VALUE ary)
{
    long low = 0, high = RARRAY_LEN(ary), mid;
    int smaller = 0, satisfied = 0;
    VALUE v, val;

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

Возвращает целочисленный индекс элемента из self, найденный бинарным поиском, или nil, если поиск не нашёл подходящего элемента.

См. Binary Searching.

Связанное: см. Methods for Fetching.

clear → self
Source
VALUE
rb_ary_clear(VALUE ary)
{
    rb_ary_modify_check(ary);
    if (ARY_SHARED_P(ary)) {
        rb_ary_unshare(ary);
        FL_SET_EMBED(ary);
        ARY_SET_EMBED_LEN(ary, 0);
    }
    else {
        ARY_SET_LEN(ary, 0);
        if (ARY_DEFAULT_SIZE * 2 < ARY_CAPA(ary)) {
            ary_resize_capa(ary, ARY_DEFAULT_SIZE * 2);
        }
    }
    ary_verify(ary);
    return ary;
}

Удаляет все элементы из self; возвращает self:

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

Связанное: см. Methods for Deleting.

collect {|element| ... } → new_array
collect → new_enumerator
Source
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; возвращает новый массив, элементами которого являются значения, возвращаемые блоком:

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

Без блока возвращает новый Enumerator.

Связанное: collect!; см. также Methods for Converting.

Также известен как: map
collect! {|element| ... } → new_array
collect! → new_enumerator
Source
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 и заменяет элемент на значение, возвращаемое блоком; возвращает self:

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

Без блока возвращает новый Enumerator.

Связанное: collect; см. также Methods for Converting.

Также известен как: map!
combination(count) {|element| ... } → self
combination(count) → new_enumerator
Source
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;
}

Когда задан блок и положительный integer-convertible object аргумент count (0 < count <= self.size), вызывает блок для каждой комбинации self размера count; возвращает self:

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

Вывод:

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

Порядок выводимых комбинаций не гарантируется.

Когда count равен нулю, вызывает блок один раз с новым пустым массивом:

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

Вывод:

[]
[]

Когда count отрицателен или больше, чем self.size и self не пуст, не вызывает блок:

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

Без блока возвращает новый Enumerator.

Связанное: Array#permutation; см. также Methods for Iterating.

compact → new_array
Source
static VALUE
rb_ary_compact(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_compact_bang(ary);
    return ary;
}

Возвращает новый массив, содержащий только не-nil элементы из self; порядок элементов сохраняется:

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

Связанное: Array#compact!; см. также Methods for Deleting.

compact! → self or nil
Source
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 элементы из self; Возвращает self, если какие-либо элементы были удалены, nil в противном случае:

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

Связанное: Array#compact; см. также Methods for Deleting.

concat(*other_arrays) → self
Source
static VALUE
rb_ary_concat_multi(int argc, VALUE *argv, VALUE ary)
{
    rb_ary_modify_check(ary);

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

    ary_verify(ary);
    return ary;
}

Добавляет к self все элементы из каждого массива в other_arrays; возвращает self:

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

Связанное: см. Methods for Assigning.

count → integer
count(object) → integer
count {|element| ... } → integer
Source
static VALUE
rb_ary_count(int argc, VALUE *argv, VALUE ary)
{
    long i, n = 0;

    if (rb_check_arity(argc, 0, 1) == 0) {
        VALUE v;

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

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

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

    return LONG2NUM(n);
}

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

Без аргументов и блока возвращает количество всех элементов:

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

С заданным аргументом object, возвращает количество элементов == до object:

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

Без аргументов и с заданным блоком вызывает блок для каждого элемента; возвращает количество элементов, для которых блок возвращает истинное значение:

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

С аргументом object и заданным блоком выводит предупреждение, игнорирует блок и возвращает количество элементов == до object.

Связанное: см. Methods for Querying.

cycle(count = nil) {|element| ... } → nil
cycle(count = nil) → new_enumerator
Source
static VALUE
rb_ary_cycle(int argc, VALUE *argv, VALUE ary)
{
    long n, i;

    rb_check_arity(argc, 0, 1);

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

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

С блоком, может вызывать блок, в зависимости от значения аргумента count; count должен быть объектом, преобразуемым в целое число, или nil.

Когда count положителен, вызывает блок с каждым элементом, затем делает это неоднократно, пока не сделает это count раз; возвращает nil:

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

Когда count равен нулю или отрицателен, не вызывает блок:

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

Когда count равен nil, цикл продолжается бесконечно:

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

Без блока возвращает новый Enumerator.

Связанное: см. Методы для итерации.

delete(object) → last_removed_object
delete(object) {|element| ... } → last_removed_object or block_return
Source
VALUE
rb_ary_delete(VALUE ary, VALUE item)
{
    VALUE v = item;
    long i1, i2;

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

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

    ary_resize_smaller(ary, i2);

    ary_verify(ary);
    return v;
}

Удаляет ноль или более элементов из self.

Без блока удаляет из self каждый элемент ele, такой что ele == object; возвращает последний удалённый элемент:

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

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

a.delete(2) # => nil

С блоком, удаляет из self каждый элемент ele, такой что ele == object.

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

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

Если такой элемент не найден, возвращает значение, возвращаемое блоком:

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

Связанное: см. Методы для удаления.

delete_at(index) → removed_object or nil
Source
static VALUE
rb_ary_delete_at_m(VALUE ary, VALUE pos)
{
    return rb_ary_delete_at(ary, NUM2LONG(pos));
}

Удаляет элемент self по заданному index, который должен быть объектом, преобразуемым в целое число.

Когда index неотрицателен, удаляет элемент со смещением index:

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

Когда index отрицателен, отсчитывает назад от конца массива:

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

Когда index находится вне диапазона, возвращает nil.

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

Связанное: см. Методы для удаления.

delete_if {|element| ... } → self
delete_if → new_numerator
Source
static VALUE
rb_ary_delete_if(VALUE ary)
{
    ary_verify(ary);
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    ary_reject_bang(ary);
    return ary;
}

С блоком, вызывает блок с каждым элементом self; удаляет элемент, если блок возвращает истинное значение; возвращает self:

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

Без блока возвращает новый Enumerator.

Связанное: см. Методы для удаления.

difference(*other_arrays = []) → new_array
Source
static VALUE
rb_ary_difference_multi(int argc, VALUE *argv, VALUE ary)
{
    VALUE ary_diff;
    long i, length;
    volatile VALUE t0;
    bool *is_hash = ALLOCV_N(bool, t0, argc);
    ary_diff = rb_ary_new();
    length = RARRAY_LEN(ary);

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

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

    ALLOCV_END(t0);

    return ary_diff;
}

Возвращает новый массив, содержащий только те элементы из self, которые не найдены ни в одном из заданных other_arrays; элементы сравниваются с помощью eql?; порядок из self сохраняется:

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

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

Связанное: Array#-; см. также Методы для объединения.

dig(index, *identifiers) → object
Source
static VALUE
rb_ary_dig(int argc, VALUE *argv, VALUE self)
{
    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    self = rb_ary_at(self, *argv);
    if (!--argc) return self;
    ++argv;
    return rb_obj_dig(argc, argv, self, Qnil);
}

Находит и возвращает объект во вложенном объекте, указанном index и identifiers; вложенные объекты могут быть экземплярами различных классов. См. Методы Dig.

Примеры:

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

Связанное: см. Методы для извлечения.

drop(count) → new_array
Source
static VALUE
rb_ary_drop(VALUE ary, VALUE n)
{
    VALUE result;
    long pos = NUM2LONG(n);
    if (pos < 0) {
        rb_raise(rb_eArgError, "attempt to drop negative size");
    }

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

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

Примеры:

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

Связанное: см. Методы для извлечения.

drop_while {|element| ... } → new_array
drop_while → new_enumerator
Source
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));
}

С блоком, вызывает блок с каждым последующим элементом self; останавливается, если блок возвращает false или nil; возвращает новый массив, опуская те элементы, для которых блок вернул истинное значение; не изменяет self:

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

Без блока возвращает новый Enumerator.

Связанное: см. Методы для извлечения.

each {|element| ... } → self
each → new_enumerator
Source
VALUE
rb_ary_each(VALUE ary)
{
    long i;
    ary_verify(ary);
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    for (i=0; i<RARRAY_LEN(ary); i++) {
        rb_yield(RARRAY_AREF(ary, i));
    }
    return ary;
}

С блоком, итерирует по элементам self, передавая каждый элемент в блок; возвращает self:

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

Вывод:

Symbol foo
String bar
Integer 2

Позволяет изменять массив во время итерации:

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

Вывод:

foo
bar

Без блока возвращает новый Enumerator.

Связанное: см. Методы для итерации.

each_index {|index| ... } → self
each_index → new_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;
}

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

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

Вывод:

0 foo
1 bar
2 2

Позволяет изменять массив во время итерации:

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

Вывод:

0
1

Без блока, возвращает новый Enumerator.

Связанные методы: см. Methods for Iterating.

empty? → true or false
Исходный код
static VALUE
rb_ary_empty_p(VALUE ary)
{
    return RBOOL(RARRAY_LEN(ary) == 0);
}

Возвращает true, если количество элементов в self равно нулю, false в противном случае.

Связанные методы: см. Methods for Querying.

eql?(other_array) → 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_array имеют одинаковый размер, и если для каждого индекса i в self, self[i].eql?(other_array[i]):

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

В противном случае возвращает false.

Этот метод отличается от метода Array#==, который сравнивает с использованием метода Object#==.

Связанные методы: см. Methods for Querying.

fetch(index) → element
fetch(index, default_value) → element or default_value
fetch(index) {|index| ... } → element or block_return_value
Исходный код
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);
}

Возвращает элемент self с смещением index, если index находится в диапазоне; index должен быть integer-convertible object.

С одним аргументом index и без блока, возвращает элемент со смещением index:

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

Если index отрицателен, отсчитывает от конца массива:

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

С аргументами index и default_value (которые могут быть любыми объектами) и без блока, возвращает default_value, если index находится вне диапазона:

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

С аргументом index и блоком, возвращает элемент со смещением index, если индекс находится в диапазоне (и блок не вызывается); в противном случае вызывает блок с индексом и возвращает его значение:

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

Связанные методы: см. Methods for Fetching.

fetch_values(*indexes) → new_array
fetch_values(*indexes) { |index| ... } → new_array
Исходный код
# File array.rb, line 210
def fetch_values(*indexes, &block)
  indexes.map! { |i| fetch(i, &block) }
  indexes
end

Без блока, возвращает новый массив, содержащий элементы self со смещениями, указанными в indexes. Каждый из indexes должен быть integer-convertible object:

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

Для отрицательного индекса отсчитывает назад от конца массива:

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

Без блока, вызывает исключение, если какой-либо индекс находится вне диапазона.

С блоком, для каждого индекса:

  • Если индекс находится в диапазоне, использует элемент self (как указано выше).

  • В противном случае вызывает блок с индексом и использует возвращаемое значение блока.

Пример:

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

Связанные методы: см. Methods for Fetching.

fill(object, start = nil, count = nil) → new_array
fill(object, range) → new_array
fill(start = nil, count = nil) {|element| ... } → new_array
fill(range) {|element| ... } → new_array
Исходный код
static VALUE
rb_ary_fill(int argc, VALUE *argv, VALUE ary)
{
    VALUE item = Qundef, arg1, arg2;
    long beg = 0, end = 0, len = 0;

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

    if (UNDEF_P(item)) {
        VALUE v;
        long i;

        for (i=beg; i<end; i++) {
            v = rb_yield(LONG2NUM(i));
            if (i>=RARRAY_LEN(ary)) break;
            ARY_SET(ary, i, v);
        }
    }
    else {
        ary_memfill(ary, beg, len, item);
    }
    return ary;
}

Заменяет выбранные элементы в self; может добавлять элементы в self; всегда возвращает self (никогда не новый массив).

Кратко:

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

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

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

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

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

Когда указаны аргументы start и count, они выбирают элементы self, которые нужно заменить; каждый из них должен быть integer-convertible object (или nil):

  • start указывает смещение с нулевой основой первого элемента для замены; nil означает ноль.

  • count — это количество последовательных элементов для замены; nil означает «все остальные».

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

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

С блоком, блок вызывается один раз для каждого элемента, который нужно заменить; значение, переданное в блок, — это индекс элемента, который нужно заменить (а не сам элемент); возвращаемое значение блока заменяет элемент:

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

Для аргументов start и count:

  • Если start неотрицателен, заменяет count элементов, начиная со смещения start:

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

    Расширяет self, если необходимо:

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

    Заполняет nil, если необходимо:

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

    Ничего не делает, если count неположителен:

    ['a', 'b', 'c', 'd'].fill('-', 2, 0)    # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 2, -100) # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 6, -100) # => ["a", "b", "c", "d"]
    
    ['a', 'b', 'c', 'd'].fill(2, 0) {|e| fail 'Cannot happen' }    # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(2, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(6, -100) {|e| fail 'Cannot happen' } # => ["a", "b", "c", "d"]
    
  • Если start отрицателен, отсчитывает назад от конца self:

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

    Расширяет self, если необходимо:

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

    Начинает с начала self, если start отрицателен и находится вне диапазона:

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

    Ничего не делает, если count неположителен:

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

Когда указан аргумент range, он должен быть объектом Range, члены которого являются числовыми; его значения begin и end определяют элементы self, которые нужно заменить:

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

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

    Если end меньше, чем begin, не заменяет элементы:

    ['a', 'b', 'c', 'd'].fill('-', 2..1)          # => ["a", "b", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(2..1) {|e| e.to_s } # => ["a", "b", "c", "d"]
    
  • Если один из них (или оба) отрицательны, отсчитывает назад от конца self:

    ['a', 'b', 'c', 'd'].fill('-', -3..2)  # => ["a", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 1..-2)  # => ["a", "-", "-", "d"]
    ['a', 'b', 'c', 'd'].fill('-', -3..-2) # => ["a", "-", "-", "d"]
    
    ['a', 'b', 'c', 'd'].fill(-3..2) {|e| e.to_s }  # => ["a", "1", "2", "d"]
    ['a', 'b', 'c', 'd'].fill(1..-2) {|e| e.to_s }  # => ["a", "1", "2", "d"]
    ['a', 'b', 'c', 'd'].fill(-3..-2) {|e| e.to_s } # => ["a", "1", "2", "d"]
    
  • Если значение end исключено (см. Range#exclude_end?), пропускает последнюю замену:

    ['a', 'b', 'c', 'd'].fill('-', 1...2)  # => ["a", "-", "c", "d"]
    ['a', 'b', 'c', 'd'].fill('-', 1...-2) # => ["a", "-", "c", "d"]
    
    ['a', 'b', 'c', 'd'].fill(1...2) {|e| e.to_s }  # => ["a", "1", "c", "d"]
    ['a', 'b', 'c', 'd'].fill(1...-2) {|e| e.to_s } # => ["a", "1", "c", "d"]
    
  • Если диапазон бесконечен (см. Endless Ranges), заменяет элементы до конца self:

    ['a', 'b', 'c', 'd'].fill('-', 1..)          # => ["a", "-", "-", "-"]
    ['a', 'b', 'c', 'd'].fill(1..) {|e| e.to_s } # => ["a", "1", "2", "3"]
    
  • Если диапазон без начала (см. Beginless Ranges), заменяет элементы с начала self:

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

Связанные методы: см. Methods for Assigning.

filter {|element| ... } → new_array
filter → new_enumerator

При заданном блоке вызывается блок с каждым элементом self; возвращает новый массив, содержащий те элементы self, для которых блок возвращает истинное значение:

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

Без блока возвращает новый Enumerator.

Связанное: см. Способы извлечения.

Псевдоним для: select
filter! {|element| ... } → self or nil
filter! → new_enumerator

При заданном блоке вызывается блок с каждым элементом self; удаляет из self те элементы, для которых блок возвращает false или nil.

Возвращает self если были удалены какие-либо элементы:

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

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

Без блока возвращает новый Enumerator.

Связанное: см. Способы удаления.

Псевдоним для: select!
find_index
Источник
Также алиас для: index
first → object or nil
first(count) → new_array
Источник
# File array.rb, line 129
def first n = unspecified = true
  if Primitive.mandatory_only?
    Primitive.attr! :leaf
    Primitive.cexpr! %q{ ary_first(self) }
  else
    if unspecified
      Primitive.cexpr! %q{ ary_first(self) }
    else
      Primitive.cexpr! %q{  ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_FIRST) }
    end
  end
end

Возвращает элементы из self, или nil; не изменяет self.

Без аргумента возвращает первый элемент (если доступен):

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

Если self пусто, возвращает nil.

[].first # => nil

С положительным целочисленным аргументом count, возвращает первые count элементов (по доступности) в новом массиве:

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

Связанное: см. Способы запроса.

flatten(depth = nil) → new_array
Источник
static VALUE
rb_ary_flatten(int argc, VALUE *argv, VALUE ary)
{
    int level = -1;
    VALUE result;

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

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

    return result;
}

Возвращает новый массив, являющийся рекурсивным сглаживанием self до depth уровней рекурсии; depth должен быть целочисленным объектом или nil. На каждом уровне рекурсии:

  • Каждый элемент, являющийся массивом, «сглаживается» (т. е., заменяется его индивидуальными элементами массива).

  • Каждый элемент, который не является массивом, остается без изменений (даже если элемент является объектом, у которого есть метод экземпляра flatten).

С положительным целочисленным аргументом depth, рекурсивно сглаживает до depth уровней:

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

С nil или отрицательным аргументом depth, сглаживает все уровни.

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

Связанное: Array#flatten!; см. также Способы преобразования.

flatten!(depth = nil) → self or nil
Источник
static VALUE
rb_ary_flatten_bang(int argc, VALUE *argv, VALUE ary)
{
    int mod = 0, level = -1;
    VALUE result, lv;

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

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

    return ary;
}

Возвращает self как рекурсивное сглаживание self до depth уровней рекурсии; depth должен быть целочисленным объектом, или nil. На каждом уровне рекурсии:

  • Каждый элемент, являющийся массивом, «сглаживается» (т. е., заменяется его индивидуальными элементами массива).

  • Каждый элемент, который не является массивом, остается без изменений (даже если элемент является объектом, у которого есть метод экземпляра flatten).

Возвращает nil если элементы не были сглажены.

С положительным целочисленным аргументом depth, рекурсивно сглаживает до depth уровней:

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

С nil или отрицательным аргументом depth, сглаживает все уровни:

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

Связанное: Array#flatten; см. также Способы присвоения.

freeze → self
Источник
VALUE
rb_ary_freeze(VALUE ary)
{
    RUBY_ASSERT(RB_TYPE_P(ary, T_ARRAY));

    if (OBJ_FROZEN(ary)) return ary;

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

    return rb_obj_freeze(ary);
}

Замораживает self (если он ещё не заморожен); возвращает self:

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

Дальнейшие изменения self недопустимы; вызывает FrozenError, если попытка изменения.

Связанное: Kernel#frozen?.

hash → integer
Источник
static VALUE
rb_ary_hash(VALUE ary)
{
    return rb_ary_hash_values(RARRAY_LEN(ary), RARRAY_CONST_PTR(ary));
}

Возвращает целочисленное значение хеша для self.

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

['a', 'b'].hash == ['a', 'b'].hash # => true
['a', 'b'].hash == ['a', 'c'].hash # => false
['a', 'b'].hash == ['a'].hash      # => false
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);
        if (rb_equal(e, item)) {
            return Qtrue;
        }
    }
    return Qfalse;
}

Возвращает, присутствует ли для некоторого элемента element в self, object == element:

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

Связанное: см. Способы запроса.

index(object) → integer or nil
index {|element| ... } → integer or nil
index → new_enumerator

Возвращает нулевой индекс указанного элемента или nil.

С аргументом object, возвращает индекс первого элемента element, для которого object == element:

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

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

Только с блоком, вызывается блок с каждым последующим элементом; возвращает индекс первого элемента, для которого блок возвращает истинное значение:

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

Возвращает nil если блок никогда не возвращает истинное значение.

Без аргумента и блока возвращает новый Enumerator.

Связанное: см. Способы запроса.

Псевдоним для: find_index
initialize_copy(other_array) → self
Исходный код
VALUE
rb_ary_replace(VALUE copy, VALUE orig)
{
    rb_ary_modify_check(copy);
    orig = to_ary(orig);
    if (copy == orig) return copy;

    rb_ary_reset(copy);

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

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

        // No allocation and exception expected that could leave `copy` in a
        // bad state from the edits above.
        ary_memcpy(copy, 0, len, RARRAY_CONST_PTR(orig));
    }
    /* Otherwise, orig is on heap and copy does not have enough space to embed
     * the contents of orig. */
    else {
        VALUE shared_root = ary_make_shared(orig);
        FL_UNSET_EMBED(copy);
        ARY_SET_PTR(copy, ARY_HEAP_PTR(orig));
        ARY_SET_LEN(copy, ARY_HEAP_LEN(orig));
        rb_ary_set_shared(copy, shared_root);
    }
    ary_verify(copy);
    return copy;
}

Заменяет элементы self элементами other_array, которые должны быть объектом, преобразуемым в массив преобразуемым в массив; возвращает self:

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

Связанное: см. Методы присваивания.

Также алиасирован как: заменить
insert(index, *objects) → self
Исходный код
static VALUE
rb_ary_insert(int argc, VALUE *argv, VALUE ary)
{
    long pos;

    rb_check_arity(argc, 1, UNLIMITED_ARGUMENTS);
    rb_ary_modify_check(ary);
    pos = NUM2LONG(argv[0]);
    if (argc == 1) return ary;
    if (pos == -1) {
        pos = RARRAY_LEN(ary);
    }
    else if (pos < 0) {
        long minpos = -RARRAY_LEN(ary) - 1;
        if (pos < minpos) {
            rb_raise(rb_eIndexError, "index %ld too small for array; minimum: %ld",
                     pos, minpos);
        }
        pos++;
    }
    rb_ary_splice(ary, pos, 0, argv + 1, argc - 1);
    return ary;
}

Вставляет заданные objects как элементы в self; возвращает self.

Когда index неотрицательно, вставляет objects перед элементом со смещением index:

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

Расширяет массив, если index выходит за пределы массива (index >= self.size):

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

Когда index отрицательно, вставляет objects после элемента со смещением index + self.size:

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

Без заданного objects ничего не делает:

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

Возбуждает IndexError, если objects заданы и index отрицательно и выходит за пределы диапазона.

Связанное: см. Методы присваивания.

inspect → new_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);
}

Возвращает новую строку, образованную вызовом метода inspect для каждого элемента массива:

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

Связанное: см. Методы преобразования.

Также алиасирован как: to_s
intersect?(other_array) → true or false
Исходный код
static VALUE
rb_ary_intersect_p(VALUE ary1, VALUE ary2)
{
    VALUE hash, v, result, shorter, longer;
    st_data_t vv;
    long i;

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

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

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

    hash = ary_make_hash(shorter);
    result = Qfalse;

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

    return result;
}

Возвращает, содержит ли other_array хотя бы один элемент, который eql? какому-то элементу self:

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

Каждый элемент должен корректно реализовывать метод hash.

Связанное: см. Методы запроса.

intersection(*other_arrays) → new_array
Исходный код
static VALUE
rb_ary_intersection_multi(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = rb_ary_dup(ary);
    int i;

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

    return result;
}

Возвращает новый массив, содержащий каждый элемент в self который eql? по крайней мере одному элементу в каждом из заданных other_arrays; дубликаты опушены:

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

Порядок из self сохраняется:

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

Возвращает копию self при отсутствии аргументов.

Связанное: см. Методы объединения.

join(separator = $,) → new_string
Исходный код
static VALUE
rb_ary_join_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE sep;

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

    return rb_ary_join(ary, sep);
}

Возвращает новую строку, образованную путём объединения преобразованных элементов self; для каждого элемента element:

  • Рекурсивно преобразует с помощью element.join(separator) если element является kind_of?(Array).

  • В противном случае преобразует с помощью element.to_s.

Без аргумента объединяет с разделителем поля вывода $,:

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

Со строковым аргументом separator заданным, объединяет с этим разделителем:

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

Рекурсивно объединяет для вложенных массивов:

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

Связанное: см. Методы преобразования.

keep_if {|element| ... } → self
keep_if → new_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; удаляет элемент из self если блок не возвращает истинное значение:

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

Без блока возвращает новый Enumerator.

Связанное: см. Методы удаления.

last → last_object or nil
last(count) → new_array
Исходный код
# File array.rb, line 166
def last n = unspecified = true
  if Primitive.mandatory_only?
    Primitive.attr! :leaf
    Primitive.cexpr! %q{ ary_last(self) }
  else
    if unspecified
      Primitive.cexpr! %q{ ary_last(self) }
    else
      Primitive.cexpr! %q{ ary_take_first_or_last_n(self, NUM2LONG(n), ARY_TAKE_LAST) }
    end
  end
end

Возвращает элементы из self или nil; self не изменяется.

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

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

С положительным целочисленным аргументом count возвращает новый массив, содержащий последние count элементов self, если доступно:

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

Связанное: см. Методы извлечения.

length → integer
Исходный код
static VALUE
rb_ary_length(VALUE ary)
{
    long len = RARRAY_LEN(ary);
    return LONG2NUM(len);
}

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

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

Связанное: см. Методы запроса.

Также алиасирован как: размер
map {|element| ... } → new_array
map → new_enumerator

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

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

Без блока возвращает новый Enumerator.

Связанное: collect!; см. также Методы преобразования.

Также алиасирован как: collect
Псевдоним для: collect
map! {|element| ... } → new_array
map! → new_enumerator

При наличии блока, вызывает блок для каждого элемента self и заменяет элемент возвращаемым значением блока; возвращает self:

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

Без блока возвращает новый Enumerator.

Связанно с: collect; см. также Методы для преобразования.

Псевдоним для: collect!
max → element
max(count) → new_array
max {|a, b| ... } → element
max(count) {|a, b| ... } → new_array
Исходный код
static VALUE
rb_ary_max(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = Qundef, v;
    VALUE num;
    long i;

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

    const long n = RARRAY_LEN(ary);
    if (rb_block_given_p()) {
        for (i = 0; i < RARRAY_LEN(ary); i++) {
           v = RARRAY_AREF(ary, i);
           if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) > 0) {
               result = v;
           }
        }
    }
    else if (n > 0) {
        result = RARRAY_AREF(ary, 0);
        if (n > 1) {
            if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
                return ary_max_opt_fixnum(ary, 1, result);
            }
            else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
                return ary_max_opt_string(ary, 1, result);
            }
            else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
                return ary_max_opt_float(ary, 1, result);
            }
            else {
                return ary_max_generic(ary, 1, result);
            }
        }
    }
    if (UNDEF_P(result)) return Qnil;
    return result;
}

Возвращает одно из следующего:

  • Элемент с максимальным значением из self.

  • Новый массив элементов с максимальным значением из self.

Не изменяет self.

Без блока, каждый элемент в self должен отвечать на метод <=> числовым значением.

Без аргумента и блока, возвращает элемент в self с максимальным значением по методу <=>:

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

С неотрицательным числовым аргументом count и без блока, возвращает новый массив не более чем с count элементами в порядке убывания по методу <=>:

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

При указании блока, блок должен возвращать числовое значение.

С блоком и без аргумента, вызывает блок self.size - 1 раз для сравнения элементов; возвращает элемент с максимальным значением по блоку:

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

С неотрицательным числовым аргументом count и блоком, возвращает новый массив не более чем с count элементами в порядке убывания по блоку:

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

Связанно с: см. Методы для извлечения.

min → element
min(count) → new_array
min {|a, b| ... } → element
min(count) {|a, b| ... } → new_array
Исходный код
static VALUE
rb_ary_min(int argc, VALUE *argv, VALUE ary)
{
    VALUE result = Qundef, v;
    VALUE num;
    long i;

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

    const long n = RARRAY_LEN(ary);
    if (rb_block_given_p()) {
        for (i = 0; i < RARRAY_LEN(ary); i++) {
           v = RARRAY_AREF(ary, i);
           if (UNDEF_P(result) || rb_cmpint(rb_yield_values(2, v, result), v, result) < 0) {
               result = v;
           }
        }
    }
    else if (n > 0) {
        result = RARRAY_AREF(ary, 0);
        if (n > 1) {
            if (FIXNUM_P(result) && CMP_OPTIMIZABLE(INTEGER)) {
                return ary_min_opt_fixnum(ary, 1, result);
            }
            else if (STRING_P(result) && CMP_OPTIMIZABLE(STRING)) {
                return ary_min_opt_string(ary, 1, result);
            }
            else if (RB_FLOAT_TYPE_P(result) && CMP_OPTIMIZABLE(FLOAT)) {
                return ary_min_opt_float(ary, 1, result);
            }
            else {
                return ary_min_generic(ary, 1, result);
            }
        }
    }
    if (UNDEF_P(result)) return Qnil;
    return result;
}

Возвращает одно из следующего:

  • Элемент с минимальным значением из self.

  • Новый массив элементов с минимальным значением из self.

Не изменяет self.

Без блока, каждый элемент в self должен отвечать на метод <=> числовым значением.

Без аргумента и блока, возвращает элемент в self с минимальным значением по методу <=>:

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

С неотрицательным числовым аргументом count и без блока, возвращает новый массив не более чем с count элементами в порядке возрастания по методу <=>:

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

При указании блока, блок должен возвращать числовое значение.

С блоком и без аргумента, вызывает блок self.size - 1 раз для сравнения элементов; возвращает элемент с минимальным значением по блоку:

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

С неотрицательным числовым аргументом count и блоком, возвращает новый массив не более чем с count элементами в порядке возрастания по блоку:

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

Связанно с: см. Методы для извлечения.

minmax → array
minmax {|a, b| ... } → array
Исходный код
static VALUE
rb_ary_minmax(VALUE ary)
{
    if (rb_block_given_p()) {
        return rb_call_super(0, NULL);
    }
    return rb_assoc_new(rb_ary_min(0, 0, ary), rb_ary_max(0, 0, ary));
}

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

Без блока, минимальное и максимальное значения определяются с помощью метода <=>:

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

С блоком, блок должен возвращать числовое значение; блок вызывается self.size - 1 раз для сравнения элементов; возвращает элементы с минимальным и максимальным значениями по блоку:

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

Связанно с: см. Методы для извлечения.

none? → true or false
none?(object) → true or false
none? {|element| ... } → true or false
Исходный код
static VALUE
rb_ary_none_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);

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

Возвращает true если ни один элемент self не удовлетворяет заданному критерию, false в противном случае.

Без блока и аргумента, возвращает true если self не содержит истинных элементов, false в противном случае:

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

С аргументом object, возвращает false если для любого элемента element, object === element; true в противном случае:

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

С блоком, вызывает блок для каждого элемента в self; возвращает true если блок не возвращает истинное значение, false в противном случае:

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

Связанно с: см. Методы для запросов.

one? → true or false
one? {|element| ... } → true or false
one?(object) → true or false
Исходный код
static VALUE
rb_ary_one_p(int argc, VALUE *argv, VALUE ary)
{
    long i, len = RARRAY_LEN(ary);
    VALUE result = Qfalse;

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

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

Без блока и аргумента, возвращает true если self имеет ровно один истинный элемент, false в противном случае:

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

С блоком, вызывает блок для каждого элемента в self; возвращает true если блок возвращает истинное значение ровно для одного элемента, false в противном случае:

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

С аргументом object, возвращает true если ровно для одного элемента element, object === element; false в противном случае:

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

Связанно с: см. Методы для запросов.

pack(template, buffer: nil) → string
Исходный код
# File pack.rb, line 7
def pack(fmt, buffer: nil)
  Primitive.pack_pack(fmt, buffer)
end

Форматирует каждый элемент в self в двоичную строку; возвращает эту строку. См. Упакованные данные.

permutation(count = self.size) {|permutation| ... } → self
permutation(count = self.size) → new_enumerator
Исходный код
static VALUE
rb_ary_permutation(int argc, VALUE *argv, VALUE ary)
{
    long r, n, i;

    n = RARRAY_LEN(ary);                  /* Array length */
    RETURN_SIZED_ENUMERATOR(ary, argc, argv, rb_ary_permutation_size);   /* Return enumerator if no block */
    r = n;
    if (rb_check_arity(argc, 0, 1) && !NIL_P(argv[0]))
        r = NUM2LONG(argv[0]);            /* Permutation size from argument */

    if (r < 0 || n < r) {
        /* no permutations: yield nothing */
    }
    else if (r == 0) { /* exactly one permutation: the zero-length array */
        rb_yield(rb_ary_new2(0));
    }
    else if (r == 1) { /* this is a special, easy case */
        for (i = 0; i < RARRAY_LEN(ary); i++) {
            rb_yield(rb_ary_new3(1, RARRAY_AREF(ary, i)));
        }
    }
    else {             /* this is the general case */
        volatile VALUE t0;
        long *p = ALLOCV_N(long, t0, r+roomof(n, sizeof(long)));
        char *used = (char*)(p + r);
        VALUE ary0 = ary_make_shared_copy(ary); /* private defensive copy of ary */
        RBASIC_CLEAR_CLASS(ary0);

        MEMZERO(used, char, n); /* initialize array */

        permute0(n, r, p, used, ary0); /* compute and yield permutations */
        ALLOCV_END(t0);
        RBASIC_SET_CLASS_RAW(ary0, rb_cArray);
    }
    return ary;
}

Перебирает все перестановки элементов self; порядок перестановок неопределён.

С блоком и положительным целым аргументом count (0 < count <= self.size) вызывает блок для каждой перестановки self размера count; возвращает self:

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

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

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

Если count равно нулю, вызывает блок один раз с пустым массивом:

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

Если count выходит за пределы допустимых значений (отрицательное или больше, чем self.size), блок не вызывается:

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

Без блока возвращает новый перечислитель Enumerator.

Связанные: Методы для итерации.

pop → object or nil
pop(count) → new_array
Исходный код
static VALUE
rb_ary_pop_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE result;

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

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

Удаляет и возвращает конечные элементы self.

Без аргумента удаляет и возвращает последний элемент, если он есть; в противном случае возвращает nil:

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

С положительным целым аргументом count возвращает новый массив, содержащий конечные count элементов self, если доступны:

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

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

Связанные: Array#push; см. также Методы для удаления.

prepend(*objects) → self

Добавляет указанные objects в начало self:

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

Связанные: Array#shift; см. также Методы для присваивания.

Псевдоним для: unshift
product(*other_arrays) → new_array
product(*other_arrays) {|combination| ... } → self
Исходный код
static VALUE
rb_ary_product(int argc, VALUE *argv, VALUE ary)
{
    int n = argc+1;    /* How many arrays we're operating on */
    volatile VALUE t0 = rb_ary_hidden_new(n);
    volatile VALUE t1 = Qundef;
    VALUE *arrays = RARRAY_PTR(t0); /* The arrays we're computing the product of */
    int *counters = ALLOCV_N(int, t1, n); /* The current position in each one */
    VALUE result = Qnil;      /* The array we'll be returning, when no block given */
    long i,j;
    long resultlen = 1;

    RBASIC_CLEAR_CLASS(t0);

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

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

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

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

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

done:
    ALLOCV_END(t1);

    return NIL_P(result) ? ary : result;
}

Вычисляет все комбинации элементов из всех массивов, включая как self, так и other_arrays:

  • Количество комбинаций равно произведению размеров всех массивов, включая как self, так и other_arrays.

  • Порядок возвращаемых комбинаций неопределён.

Без блока возвращает комбинации как массив массивов:

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

Если self или любой аргумент пуст, возвращает пустой массив:

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

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

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

С блоком вызывает блок для каждой комбинации; возвращает self:

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

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

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

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

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

Связанные: см. Методы для объединения.

push(*objects) → self
Исходный код
static VALUE
rb_ary_push_m(int argc, VALUE *argv, VALUE ary)
{
    return rb_ary_cat(ary, argv, argc);
}

Добавляет каждый аргумент в objects в конец self; возвращает self:

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

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

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

Связанные: см. Методы для присваивания.

Также псевдоним: append
rassoc(object) → found_array or nil
Исходный код
VALUE
rb_ary_rassoc(VALUE ary, VALUE value)
{
    long i;
    VALUE v;

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

Возвращает первый элемент ele в self такой, что ele является массивом и ele[1] == object:

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

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

Связанные: Array#assoc; см. также Методы для извлечения.

reject {|element| ... } → new_array
reject → new_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, для которых блок возвращает false или nil:

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

Без блока возвращает новый перечислитель Enumerator.

Связанные: Методы для извлечения.

reject! {|element| ... } → self or nil
reject! → new_enumerator
Исходный код
static VALUE
rb_ary_reject_bang(VALUE ary)
{
    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    rb_ary_modify(ary);
    return ary_reject_bang(ary);
}

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

Возвращает self если какие-либо элементы были удалены:

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

Возвращает nil если элементы не удалялись.

Без блока возвращает новый перечислитель Enumerator.

Связанные: см. Методы для удаления.

repeated_combination(size) {|combination| ... } → self
repeated_combination(size) → new_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;
}

С блоком вызывает блок для каждой повторяющейся комбинации длины size элементов self; каждая комбинация — массив; возвращает self. Порядок комбинаций неопределён.

Если задан положительный целый аргумент size, вызывает блок для каждой повторяющейся комбинации из size кортежей элементов self. Количество комбинаций равно (size+1)(size+2)/2.

Примеры:

  • Если size равно 1:

    c = []
    [0, 1, 2].repeated_combination(1) {|combination| c.push(combination) }
    c # => [[0], [1], [2]]
    
  • Если size равно 2:

    c = []
    [0, 1, 2].repeated_combination(2) {|combination| c.push(combination) }
    c # => [[0, 0], [0, 1], [0, 2], [1, 1], [1, 2], [2, 2]]
    

Если size равно нулю, вызывает блок один раз с пустым массивом.

Если size отрицательно, блок не вызывается:

[0, 1, 2].repeated_combination(-1) {|combination| fail 'Cannot happen' }

Без блока возвращает новый перечислитель Enumerator.

Связанные: см. Методы для объединения.

repeated_permutation(size) {|permutation| ... } → self
repeated_permutation(size) → new_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;
}

При наличии блока вызывается блок со всеми повторяющимися перестановками длины size элементов массива self; каждая перестановка — массив; возвращает self. Порядок перестановок неопределён.

Если задан положительный целочисленный аргумент size, вызывается блок со всеми повторяющимися перестановками кортежей длины size элементов массива self. Количество перестановок равно self.size**size.

Примеры:

  • size равно 1:

    p = []
    [0, 1, 2].repeated_permutation(1) {|permutation| p.push(permutation) }
    p # => [[0], [1], [2]]
    
  • size равно 2:

    p = []
    [0, 1, 2].repeated_permutation(2) {|permutation| p.push(permutation) }
    p # => [[0, 0], [0, 1], [0, 2], [1, 0], [1, 1], [1, 2], [2, 0], [2, 1], [2, 2]]
    

Если size равно нулю, блок вызывается один раз с пустым массивом.

Если size отрицательно, блок не вызывается:

[0, 1, 2].repeated_permutation(-1) {|permutation| fail 'Cannot happen' }

Без блока возвращается новый Enumerator.

Связанные: см. Способы комбинирования.

replace(other_array) → self

Заменяет элементы self элементами other_array, которые должны быть объектом, преобразуемым в массив ; объект, преобразуемый в массив; возвращает self.

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

Связанные: см. Методы присваивания.

Псевдоним для: initialize_copy
reverse → new_array
Исходный код
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 в обратном порядке:

[0, 1, 2].reverse # => [2, 1, 0]

Связанные: см. Способы комбинирования.

reverse! → self
Исходный код
static VALUE
rb_ary_reverse_bang(VALUE ary)
{
    return rb_ary_reverse(ary);
}

Изменяет порядок элементов self; возвращает self.

a = [0, 1, 2]
a.reverse! # => [2, 1, 0]
a          # => [2, 1, 0]

Связанные: см. Методы присваивания.

reverse_each {|element| ... } → self
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;
}

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

a = []
[0, 1, 2].reverse_each {|element| a.push(element) }
a # => [2, 1, 0]

Разрешает изменение массива во время итерации:

a = ['a', 'b', 'c']
a.reverse_each {|element| a.clear if element.start_with?('b') }
a # => []

Без блока возвращает новый Enumerator.

Связанные: см. Методы итерирования.

rindex(object) → integer or nil
rindex {|element| ... } → integer or nil
rindex → new_enumerator
Исходный код
static VALUE
rb_ary_rindex(int argc, VALUE *argv, VALUE ary)
{
    VALUE val;
    long i = RARRAY_LEN(ary), len;

    if (argc == 0) {
        RETURN_ENUMERATOR(ary, 0, 0);
        while (i--) {
            if (RTEST(rb_yield(RARRAY_AREF(ary, i))))
                return LONG2NUM(i);
            if (i > (len = RARRAY_LEN(ary))) {
                i = len;
            }
        }
        return Qnil;
    }
    rb_check_arity(argc, 0, 1);
    val = argv[0];
    if (rb_block_given_p())
        rb_warn("given block not used");
    while (i--) {
        VALUE e = RARRAY_AREF(ary, i);
        if (rb_equal(e, val)) {
            return LONG2NUM(i);
        }
        if (i > RARRAY_LEN(ary)) {
            break;
        }
    }
    return Qnil;
}

Возвращает индекс последнего элемента, для которого выполняется object == element.

При заданном аргументе object, возвращает индекс последнего такого элемента, найденного:

a = [:foo, 'bar', 2, 'bar']
a.rindex('bar') # => 3

Возвращает nil , если такой объект не найден.

При наличии блока, вызывается блок с каждым элементом; возвращает индекс последнего элемента, для которого блок возвращает истинное значение:

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

Возвращает nil , если блок никогда не возвращает истинное значение.

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

Связанные: см. Методы запроса.

rotate(count = 1) → new_array
Исходный код
static VALUE
rb_ary_rotate_m(int argc, VALUE *argv, VALUE ary)
{
    VALUE rotated;
    const VALUE *ptr;
    long len;
    long cnt = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);

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

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

При неотрицательном числовом count, вращает элементы с начала до конца:

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

Если count велико, использует count % array.size в качестве счётчика:

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

При count равном нулю, не вращает элементы:

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

При отрицательном числовом count, вращает в обратном направлении, от конца к началу:

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

Если count мало (далеко от нуля), использует count % array.size в качестве счётчика:

[0, 1, 2, 3].rotate(-21) # => [3, 0, 1, 2]

Связанные: см. Методы извлечения.

rotate!(count = 1) → self
Исходный код
static VALUE
rb_ary_rotate_bang(int argc, VALUE *argv, VALUE ary)
{
    long n = (rb_check_arity(argc, 0, 1) ? NUM2LONG(argv[0]) : 1);
    rb_ary_rotate(ary, n);
    return ary;
}

Вращает self на месте, перемещая элементы с одного конца на другой; возвращает self.

При неотрицательном числовом count, вращает count элементов с начала до конца:

[0, 1, 2, 3].rotate!(2)   # => [2, 3, 0, 1]
[0, 1, 2, 3].rotate!(2.1) # => [2, 3, 0, 1]

Если count велико, использует count % array.size в качестве счётчика:

[0, 1, 2, 3].rotate!(21) # => [1, 2, 3, 0]

Если count равно нулю, не вращает элементы:

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

При отрицательном числовом count, вращает в обратном направлении, от конца к началу:

[0, 1, 2, 3].rotate!(-1) # => [3, 0, 1, 2]

Если count мало (далеко от нуля), использует count % array.size в качестве счётчика:

[0, 1, 2, 3].rotate!(-21) # => [3, 0, 1, 2]

Связанные: см. Методы присваивания.

sample(random: Random) → объект
sample(count, random: Random) → новый_массив
Исходный код
# File array.rb, line 95
def sample(n = (ary = false), random: Random)
  if Primitive.mandatory_only?
    # Primitive.cexpr! %{ rb_ary_sample(self, rb_cRandom, Qfalse, Qfalse) }
    Primitive.ary_sample0
  else
    # Primitive.cexpr! %{ rb_ary_sample(self, random, n, ary) }
    Primitive.ary_sample(random, n, ary)
  end
end

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

Без аргумента count, возвращает один случайный элемент из self:

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

Возвращает nil , если self пусто:

[].sample # => nil

С заданным положительным числовым аргументом count, возвращает новый массив, содержащий count случайных элементов из self:

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

Порядок элементов в результирующем массиве не связан с порядком self.

Возвращает новый пустой Array, если self пуст:

[].sample(4) # => []

В self могут быть дубликаты:

a = [1, 1, 1, 2, 2, 3]
a.sample(a.size) # => [1, 1, 3, 2, 1, 2]

Возвращает не более a.size элементов (потому что новые дубликаты не создаются):

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

Объект, заданный в ключевом аргументе random используется в качестве генератора случайных чисел:

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

Связанные: см. Способы получения элементов.

select {|элемент| ... } → новый_массив
select → новый_перечислитель
Исходный код
static VALUE
rb_ary_select(VALUE ary)
{
    VALUE result;
    long i;

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

При передаче блока, вызов блока выполняется для каждого элемента self; возвращает новый массив, содержащий те элементы self из self для которых блок возвращает истинное значение:

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

Без блока, возвращает новый Enumerator.

Связанные: см. Способы получения элементов.

Также алиасирован как: filter, filter
select! {|элемент| ... } → self или nil
select! → новый_перечислитель
Исходный код
static VALUE
rb_ary_select_bang(VALUE ary)
{
    struct select_bang_arg args;

    RETURN_SIZED_ENUMERATOR(ary, 0, 0, ary_enum_length);
    rb_ary_modify(ary);

    args.ary = ary;
    args.len[0] = args.len[1] = 0;
    return rb_ensure(select_bang_i, (VALUE)&args, select_bang_ensure, (VALUE)&args);
}

При передаче блока, вызов блока выполняется для каждого элемента self; удаляет из self те элементы, для которых блок возвращает false или nil.

Возвращает self , если были удалены какие-либо элементы:

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

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

Без блока, возвращает новый Enumerator.

Связанные: см. Методы для удаления.

Также алиасирован как: filter!
shelljoin → строка
Исходный код
# File lib/shellwords.rb, line 251
def shelljoin
  Shellwords.join(self)
end

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

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

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

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

    rb_ary_modify_check(ary);
    result = ary_take_first_or_last(argc, argv, ary, ARY_TAKE_FIRST);
    n = RARRAY_LEN(result);
    rb_ary_behead(ary,n);

    return result;
}

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

Без аргумента, удаляет и возвращает один элемент, если доступен, в противном случае nil:

a = [0, 1, 2, 3]
a.shift  # => 0
a        # => [1, 2, 3]
[].shift # => nil

С заданным положительным числовым аргументом count , удаляет и возвращает первые count элементов:

a = [0, 1, 2, 3]
a.shift(2)   # => [0, 1]
a            # => [2, 3]
a.shift(1.1) # => [2]
a            # => [3]
a.shift(0)   # => []
a            # => [3]

Если count большой, удаляет и возвращает все элементы:

a = [0, 1, 2, 3]
a.shift(50) # => [0, 1, 2, 3]
a           # => []

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

Связанные: см. Методы для удаления.

shuffle(random: Random) → новый_массив
Исходный код
# File array.rb, line 45
def shuffle(random: Random)
  Primitive.rb_ary_shuffle(random)
end

Возвращает новый массив, содержащий все элементы из self в случайном порядке, выбранном объектом, заданным в ключевом аргументе random:

a =            [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a.shuffle # => [0, 8, 1, 9, 6, 3, 4, 7, 2, 5]
a.shuffle # => [8, 9, 0, 5, 1, 2, 6, 4, 7, 3]

Дублирующиеся элементы включены:

a =            [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
a.shuffle # => [1, 0, 1, 1, 0, 0, 1, 0, 0, 1]
a.shuffle # => [1, 1, 0, 0, 0, 1, 1, 0, 0, 1]

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

Связанные: см. Способы получения элементов.

shuffle!(random: Random) → self
Исходный код
# File array.rb, line 22
def shuffle!(random: Random)
  Primitive.rb_ary_shuffle_bang(random)
end

Перемешивает все элементы в self в случайном порядке, выбранном объектом, заданным в ключевом аргументе random. Возвращает self:

a =             [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]
a.shuffle! # => [5, 3, 8, 7, 6, 1, 9, 4, 2, 0]
a.shuffle! # => [9, 4, 0, 6, 2, 8, 1, 5, 3, 7]

Дубликаты элементов включены:

a =             [0, 1, 0, 1, 0, 1, 0, 1, 0, 1]
a.shuffle! # => [1, 0, 0, 1, 1, 0, 1, 0, 0, 1]
a.shuffle! # => [0, 1, 0, 1, 1, 0, 1, 0, 1, 0]

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

Связанные: см. Методы присваивания.

size → целое число

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

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

Связанные: см. Методы запроса.

Псевдоним для: length
slice(index) → объект или nil
slice(start, length) → объект или nil
slice(range) → объект или nil
slice(aseq) → объект или nil

Возвращает элементы из self; не изменяет self.

Вкратце:

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

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

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

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

Когда задан единственный целочисленный аргумент index , возвращает элемент с смещением index:

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

Если index отрицательный, отсчёт ведётся от конца self:

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

Если index выходит за пределы диапазона, возвращает nil.

Когда заданы два целочисленных аргумента Integer и start , возвращает новый массив Array размера length содержащий последовательные элементы, начиная с смещения start:

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

Если start + length больше self.length, возвращает все элементы от смещения start до конца:

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

Если start == self.size и length >= 0, возвращает новый пустой массив Array.

Если length отрицательный, возвращает nil.

Когда задан единственный аргумент-диапазон Range , обрабатывает range как range.min (выше) и range.size как length (выше):

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

Особый случай: Если range.start == a.size, возвращает новый пустой массив Array.

Если range.end отрицательный, рассчитывает конечный индекс с конца:

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

Если range.start отрицательный, рассчитывает начальный индекс с конца:

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

Если range.start больше размера массива, возвращает nil.

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

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

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

См. также: Методы извлечения.

Псевдоним для: []
slice!(index) → объект или nil
slice!(start, length) → new_array или nil
slice!(range) → new_array или nil
Исходный код
static VALUE
rb_ary_slice_bang(int argc, VALUE *argv, VALUE ary)
{
    VALUE arg1;
    long pos, len;

    rb_ary_modify_check(ary);
    rb_check_arity(argc, 1, 2);
    arg1 = argv[0];

    if (argc == 2) {
        pos = NUM2LONG(argv[0]);
        len = NUM2LONG(argv[1]);
        return ary_slice_bang_by_rb_ary_splice(ary, pos, len);
    }

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

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

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

При задании числового аргумента index удаляет и возвращает элемент со смещением index:

a = ['a', 'b', 'c', 'd']
a.slice!(2)   # => "c"
a             # => ["a", "b", "d"]
a.slice!(2.1) # => "d"
a             # => ["a", "b"]

Если index отрицательный, отсчёт ведётся от конца self:

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

Если index выходит за пределы диапазона, возвращает nil.

При задании числовых аргументов start и length удаляет length элементов из self начиная с нулевого смещения start; возвращает удалённые объекты в новом массиве:

a = ['a', 'b', 'c', 'd']
a.slice!(1, 2)     # => ["b", "c"]
a                  # => ["a", "d"]
a.slice!(0.1, 1.1) # => ["a"]
a                  # => ["d"]

Если start отрицательный, отсчёт ведётся с конца self:

a = ['a', 'b', 'c', 'd']
a.slice!(-2, 1) # => ["c"]
a               # => ["a", "b", "d"]

Если start выходит за пределы диапазона, возвращает nil:

a = ['a', 'b', 'c', 'd']
a.slice!(5, 1)  # => nil
a.slice!(-5, 1) # => nil

Если start + length превышает размер массива, удаляет и возвращает все элементы от смещения start до конца:

a = ['a', 'b', 'c', 'd']
a.slice!(2, 50) # => ["c", "d"]
a               # => ["a", "b"]

Если start == a.size и length неотрицательные, возвращает новый пустой массив.

Если length отрицательный, возвращает nil.

При задании аргумента-диапазона Range , обрабатывает range.min как start (как выше) и range.size как length (как выше):

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

Если range.start == a.size, возвращает новый пустой массив:

a = ['a', 'b', 'c', 'd']
a.slice!(4..5) # => []

Если range.start больше размера массива, возвращает nil:

a = ['a', 'b', 'c', 'd']
a.slice!(5..6) # => nil

Если range.start отрицательный, рассчитывает начальный индекс, отсчитывая назад от конца self:

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

Если range.end отрицательный, рассчитывает конечный индекс, отсчитывая назад от конца self:

a = ['a', 'b', 'c', 'd']
a.slice!(0..-2) # => ["a", "b", "c"]

См. также: Методы удаления.

sort → new_array
sort {|a, b| ... } → new_array
Исходный код
VALUE
rb_ary_sort(VALUE ary)
{
    ary = rb_ary_dup(ary);
    rb_ary_sort_bang(ary);
    return ary;
}

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

Без блока сравнивает элементы с помощью оператора <=> (см. Object#<=>):

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

При заданном блоке вызывает блок для каждой пары элементов из self; для каждой пары a и b, блок должен возвращать числовое значение:

  • Отрицательное, если b должен следовать за a.

  • Ноль, если a и b эквивалентны.

  • Положительное, если a должен следовать за b.

Пример:

a = [3, 2, 0, 1]
a.sort {|a, b| a <=> b } # => [0, 1, 2, 3]
a.sort {|a, b| b <=> a } # => [3, 2, 1, 0]

Если блок возвращает ноль, порядок a и b неопределён и может быть нестабильным.

См. также: Методы извлечения.

sort! → self
sort! {|a, b| ... } → self
Исходный код
VALUE
rb_ary_sort_bang(VALUE ary)
{
    rb_ary_modify(ary);
    RUBY_ASSERT(!ARY_SHARED_P(ary));
    if (RARRAY_LEN(ary) > 1) {
        VALUE tmp = ary_make_substitution(ary); /* only ary refers tmp */
        struct ary_sort_data data;
        long len = RARRAY_LEN(ary);
        RBASIC_CLEAR_CLASS(tmp);
        data.ary = tmp;
        data.receiver = ary;
        RARRAY_PTR_USE(tmp, ptr, {
            ruby_qsort(ptr, len, sizeof(VALUE),
                       rb_block_given_p()?sort_1:sort_2, &data);
        }); /* WB: no new reference */
        rb_ary_modify(ary);
        if (ARY_EMBED_P(tmp)) {
            if (ARY_SHARED_P(ary)) { /* ary might be destructively operated in the given block */
                rb_ary_unshare(ary);
                FL_SET_EMBED(ary);
            }
            if (ARY_EMBED_LEN(tmp) > ARY_CAPA(ary)) {
                ary_resize_capa(ary, ARY_EMBED_LEN(tmp));
            }
            ary_memcpy(ary, 0, ARY_EMBED_LEN(tmp), ARY_EMBED_PTR(tmp));
            ARY_SET_LEN(ary, ARY_EMBED_LEN(tmp));
        }
        else {
            if (!ARY_EMBED_P(ary) && ARY_HEAP_PTR(ary) == ARY_HEAP_PTR(tmp)) {
                FL_UNSET_SHARED(ary);
                ARY_SET_CAPA(ary, RARRAY_LEN(tmp));
            }
            else {
                RUBY_ASSERT(!ARY_SHARED_P(tmp));
                if (ARY_EMBED_P(ary)) {
                    FL_UNSET_EMBED(ary);
                }
                else if (ARY_SHARED_P(ary)) {
                    /* ary might be destructively operated in the given block */
                    rb_ary_unshare(ary);
                }
                else {
                    ary_heap_free(ary);
                }
                ARY_SET_PTR(ary, ARY_HEAP_PTR(tmp));
                ARY_SET_HEAP_LEN(ary, len);
                ARY_SET_CAPA(ary, ARY_HEAP_LEN(tmp));
            }
            /* tmp was lost ownership for the ptr */
            FL_UNSET(tmp, FL_FREEZE);
            FL_SET_EMBED(tmp);
            ARY_SET_EMBED_LEN(tmp, 0);
            FL_SET(tmp, FL_FREEZE);
        }
        /* tmp will be GC'ed. */
        RBASIC_SET_CLASS_RAW(tmp, rb_cArray); /* rb_cArray must be marked */
    }
    ary_verify(ary);
    return ary;
}

Как Array#sort, но возвращает self с отсортированными элементами на месте.

См. также: Методы присваивания.

sort_by! {|element| ... } → self
sort_by! → new_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.

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

a = ['aaaa', 'bbb', 'cc', 'd']
a.sort_by! {|element| element.size }
a # => ["d", "cc", "bbb", "aaaa"]

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

Без блока возвращает новый перечислитель Enumerator.

См. также: Методы присваивания.

sum(init = 0) → object
sum(init = 0) {|element| ... } → object
Source
static VALUE
rb_ary_sum(int argc, VALUE *argv, VALUE ary)
{
    VALUE e, v, r;
    long i, n;
    int block_given;

    v = (rb_check_arity(argc, 0, 1) ? argv[0] : LONG2FIX(0));

    block_given = rb_block_given_p();

    if (RARRAY_LEN(ary) == 0)
        return v;

    n = 0;
    r = Qundef;

    if (!FIXNUM_P(v) && !RB_BIGNUM_TYPE_P(v) && !RB_TYPE_P(v, T_RATIONAL)) {
        i = 0;
        goto init_is_a_value;
    }

    for (i = 0; i < RARRAY_LEN(ary); i++) {
        e = RARRAY_AREF(ary, i);
        if (block_given)
            e = rb_yield(e);
        if (FIXNUM_P(e)) {
            n += FIX2LONG(e); /* should not overflow long type */
            if (!FIXABLE(n)) {
                v = rb_big_plus(LONG2NUM(n), v);
                n = 0;
            }
        }
        else if (RB_BIGNUM_TYPE_P(e))
            v = rb_big_plus(e, v);
        else if (RB_TYPE_P(e, T_RATIONAL)) {
            if (UNDEF_P(r))
                r = e;
            else
                r = rb_rational_plus(r, e);
        }
        else
            goto not_exact;
    }
    v = finish_exact_sum(n, r, v, argc!=0);
    return v;

  not_exact:
    v = finish_exact_sum(n, r, v, i!=0);

    if (RB_FLOAT_TYPE_P(e)) {
        /*
         * Kahan-Babuska balancing compensated summation algorithm
         * See https://link.springer.com/article/10.1007/s00607-005-0139-x
         */
        double f, c;
        double x, t;

        f = NUM2DBL(v);
        c = 0.0;
        goto has_float_value;
        for (; i < RARRAY_LEN(ary); i++) {
            e = RARRAY_AREF(ary, i);
            if (block_given)
                e = rb_yield(e);
            if (RB_FLOAT_TYPE_P(e))
              has_float_value:
                x = RFLOAT_VALUE(e);
            else if (FIXNUM_P(e))
                x = FIX2LONG(e);
            else if (RB_BIGNUM_TYPE_P(e))
                x = rb_big2dbl(e);
            else if (RB_TYPE_P(e, T_RATIONAL))
                x = rb_num2dbl(e);
            else
                goto not_float;

            if (isnan(f)) continue;
            if (isnan(x)) {
                f = x;
                continue;
            }
            if (isinf(x)) {
                if (isinf(f) && signbit(x) != signbit(f))
                    f = NAN;
                else
                    f = x;
                continue;
            }
            if (isinf(f)) continue;

            t = f + x;
            if (fabs(f) >= fabs(x))
                c += ((f - t) + x);
            else
                c += ((x - t) + f);
            f = t;
        }
        f += c;
        return DBL2NUM(f);

      not_float:
        v = DBL2NUM(f);
    }

    goto has_some_value;
    init_is_a_value:
    for (; i < RARRAY_LEN(ary); i++) {
        e = RARRAY_AREF(ary, i);
        if (block_given)
            e = rb_yield(e);
      has_some_value:
        v = rb_funcall(v, idPLUS, 1, e);
    }
    return v;
}

Без блока возвращает сумму init и всех элементов self; для массива array и значения init, эквивалентно:

sum = init
array.each {|element| sum += element }
sum

Например, [e0, e1, e2].sum возвращает init + e0 + e1 + e2.

Примеры:

[0, 1, 2, 3].sum                 # => 6
[0, 1, 2, 3].sum(100)            # => 106
['abc', 'def', 'ghi'].sum('jkl') # => "jklabcdefghi"
[[:foo, :bar], ['foo', 'bar']].sum([2, 3])
# => [2, 3, :foo, :bar, "foo", "bar"]

Значение init и элементы не обязательно должны быть числовыми, но все должны быть совместимы с +:

# Raises TypeError: Array can't be coerced into Integer.
[[:foo, :bar], ['foo', 'bar']].sum(2)

С заданным блоком вызывает блок для каждого элемента self; возвращаемое значение блока (вместо самого элемента) используется как слагаемое:

['zero', 1, :two].sum('Coerced and concatenated: ') {|element| element.to_s }
# => "Coerced and concatenated: zero1two"

Примечания:

  • Array#join и Array#flatten могут быть быстрее, чем Array#sum для массива строк или массива массивов.

  • Array#sum метод может не учитывать переопределение метода “+”, таких как Integer#+.

take(count) → new_array
Source
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);
}

Возвращает новый массив, содержащий первые count элемента self (если доступны); count должно быть неотрицательным числом; не изменяет self:

a = ['a', 'b', 'c', 'd']
a.take(2)   # => ["a", "b"]
a.take(2.1) # => ["a", "b"]
a.take(50)  # => ["a", "b", "c", "d"]
a.take(0)   # => []

Связанное: см. Methods for Fetching.

take_while {|element| ... } → new_array
take_while → new_enumerator
Source
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));
}

С заданным блоком вызывает блок для каждого последующего элемента self; прекращает итерацию, если блок возвращает false или nil; возвращает новый массив, содержащий элементы, для которых блок вернул истинное значение:

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

Без блока возвращает новый Enumerator.

Не изменяет self.

Связанное: см. Methods for Fetching.

to_a → self or new_array
Source
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, возвращает self.

В противном случае возвращает новый массив, содержащий элементы self:

class MyArray < Array; end
my_a = MyArray.new(['foo', 'bar', 'two'])
a = my_a.to_a
a # => ["foo", "bar", "two"]
a.class # => Array # Not MyArray.

Связанное: см. Methods for Converting.

to_ary → self
Source
static VALUE
rb_ary_to_ary_m(VALUE ary)
{
    return ary;
}

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

to_h → new_hash
to_h {|element| ... } → new_hash
Source
static VALUE
rb_ary_to_h(VALUE ary)
{
    long i;
    VALUE hash = rb_hash_new_with_size(RARRAY_LEN(ary));
    int block_given = rb_block_given_p();

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

Возвращает новый хэш, образованный из self.

Без блока каждый элемент self должен быть 2-элементным подмассивом; формирует каждый подмассив в пару ключ-значение в новом хэше:

a = [['foo', 'zero'], ['bar', 'one'], ['baz', 'two']]
a.to_h # => {"foo"=>"zero", "bar"=>"one", "baz"=>"two"}
[].to_h # => {}

С заданным блоком блок должен возвращать 2-элементный массив; вызывает блок для каждого элемента self; формирует каждый возвращаемый массив в пару ключ-значение в возвращаемом хэше:

a = ['foo', :bar, 1, [2, 3], {baz: 4}]
a.to_h {|element| [element, element.class] }
# => {"foo"=>String, :bar=>Symbol, 1=>Integer, [2, 3]=>Array, {:baz=>4}=>Hash}

Связанное: см. Methods for Converting.

to_s → new_string

Возвращает новую строку, образованную вызовом метода inspect для каждого элемента массива:

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

Связанное: см. Methods for Converting.

Alias for: inspect
transpose → new_array
Source
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 как transposed matrix:

a = [[:a0, :a1], [:b0, :b1], [:c0, :c1]]
a.transpose # => [[:a0, :b0, :c0], [:a1, :b1, :c1]]

Элементы self должны быть одинакового размера.

Связанное: см. Methods for Converting.

union(*other_arrays) → new_array
Source
static VALUE
rb_ary_union_multi(int argc, VALUE *argv, VALUE ary)
{
    int i;
    long sum;
    VALUE hash;

    sum = RARRAY_LEN(ary);
    for (i = 0; i < argc; i++) {
        argv[i] = to_ary(argv[i]);
        sum += RARRAY_LEN(argv[i]);
    }

    if (sum <= SMALL_ARRAY_LEN) {
        VALUE ary_union = rb_ary_new();

        rb_ary_union(ary_union, ary);
        for (i = 0; i < argc; i++) rb_ary_union(ary_union, argv[i]);

        return ary_union;
    }

    hash = ary_make_hash(ary);
    for (i = 0; i < argc; i++) rb_ary_union_hash(hash, argv[i]);

    return rb_hash_values(hash);
}

Возвращает новый массив, который является объединением элементов self и всех заданных массивов other_arrays; элементы сравниваются с использованием eql?:

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

Удаляет дубликаты (сохраняя первый найденный):

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

Сохраняет порядок (сохраняя позицию первого найденного):

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

Без аргументов возвращает копию self.

Связанное: см. Methods for Combining.

uniq → new_array
uniq {|element| ... } → new_array
Source
static VALUE
rb_ary_uniq(VALUE ary)
{
    VALUE hash, uniq;

    if (RARRAY_LEN(ary) <= 1) {
        hash = 0;
        uniq = rb_ary_dup(ary);
    }
    else if (rb_block_given_p()) {
        hash = ary_make_hash_by(ary);
        uniq = rb_hash_values(hash);
    }
    else {
        hash = ary_make_hash(ary);
        uniq = rb_hash_values(hash);
    }

    return uniq;
}

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

Без блока идентифицирует и пропускает дубликаты, используя метод eql? для сравнения элементов:

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

С заданным блоком вызывает блок для каждого элемента; идентифицирует и пропускает «дублирующиеся» элементы, используя метод eql? для сравнения возвращаемых значений блока; то есть элемент является дубликатом, если его возвращаемое значение блока совпадает с возвращаемым значением предыдущего элемента:

a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
a.uniq {|element| element.size } # => ["a", "aa", "aaa"]

Связанное: Methods for Fetching.

uniq! → self или nil
uniq! {|элемент| ... } → self или nil
Исходный код
static VALUE
rb_ary_uniq_bang(VALUE ary)
{
    VALUE hash;
    long hash_size;

    rb_ary_modify_check(ary);
    if (RARRAY_LEN(ary) <= 1)
        return Qnil;
    if (rb_block_given_p())
        hash = ary_make_hash_by(ary);
    else
        hash = ary_make_hash(ary);

    hash_size = RHASH_SIZE(hash);
    if (RARRAY_LEN(ary) == hash_size) {
        return Qnil;
    }
    rb_ary_modify_check(ary);
    ARY_SET_LEN(ary, 0);
    if (ARY_SHARED_P(ary)) {
        rb_ary_unshare(ary);
        FL_SET_EMBED(ary);
    }
    ary_resize_capa(ary, hash_size);
    rb_hash_foreach(hash, push_value, ary);

    return ary;
}

Удаляет дублирующие элементы из self, сохраняя при этом первое вхождение; возвращает self при удалении каких-либо элементов, nil в противном случае.

Без блока идентифицирует и удаляет элементы, используя метод eql? для сравнения элементов:

a = [0, 0, 1, 1, 2, 2]
a.uniq! # => [0, 1, 2]
a.uniq! # => nil

С блоком, вызывает блок для каждого элемента; идентифицирует и пропускает "дублирующие" элементы, используя метод eql? для сравнения значений, возвращаемых блоком; то есть элемент является дублирующим, если его значение, возвращаемое блоком, совпадает с значением предыдущего элемента:

a = ['a', 'aa', 'aaa', 'b', 'bb', 'bbb']
a.uniq! {|element| element.size } # => ["a", "aa", "aaa"]
a.uniq! {|element| element.size } # => nil

См. также: Методы удаления.

unshift(*объекты) → self
Исходный код
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;
}

Добавляет указанные objects в начало self:

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

См. также: Array#shift; см. также Методы присваивания.

Также алиас: prepend
values_at(*спецификаторы) → новый_массив
Исходный код
static VALUE
rb_ary_values_at(int argc, VALUE *argv, VALUE ary)
{
    long i, olen = RARRAY_LEN(ary);
    VALUE result = rb_ary_new_capa(argc);
    for (i = 0; i < argc; ++i) {
        append_values_at_single(result, ary, olen, argv[i]);
    }
    RB_GC_GUARD(ary);
    return result;
}

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

Объекты, включенные в возвращаемый массив, являются элементами self, выбранными заданными specifiers, каждый из которых должен быть числовым индексом или Range.

Кратко:

a = ['a', 'b', 'c', 'd']

# Index specifiers.
a.values_at(2, 0, 2, 0)     # => ["c", "a", "c", "a"] # May repeat.
a.values_at(-4, -3, -2, -1) # => ["a", "b", "c", "d"] # Counts backwards if negative.
a.values_at(-50, 50)        # => [nil, nil]           # Outside of self.

# Range specifiers.
a.values_at(1..3)       # => ["b", "c", "d"] # From range.begin to range.end.
a.values_at(1...3)      # => ["b", "c"]      # End excluded.
a.values_at(3..1)       # => []              # No such elements.

a.values_at(-3..3)  # => ["b", "c", "d"]     # Negative range.begin counts backwards.
a.values_at(-50..3)                          # Raises RangeError.

a.values_at(1..-2)  # => ["b", "c"]          # Negative range.end counts backwards.
a.values_at(1..-50) # => []                  # No such elements.

# Mixture of specifiers.
a.values_at(2..3, 3, 0..1, 0) # => ["c", "d", "d", "a", "b", "a"]

Без указанных specifiers возвращает новый пустой массив:

a = ['a', 'b', 'c', 'd']
a.values_at # => []

Для каждого числового спецификатора index, включает элемент:

  • Для каждого неотрицательного числового спецификатора index находящегося в пределах диапазона (меньше self.size), включает элемент по смещению index:

    a.values_at(0, 2)     # => ["a", "c"]
    a.values_at(0.1, 2.9) # => ["a", "c"]
    
  • Для каждого отрицательного числового index находящегося в пределах диапазона (больше или равно - self.size), считает назад от конца self:

    a.values_at(-1, -4) # => ["d", "a"]
    

Указанные индексы могут быть в любом порядке и могут повторяться:

a.values_at(2, 0, 1, 0, 2) # => ["c", "a", "b", "a", "c"]

Для каждого index находящегося вне диапазона, включает nil:

a.values_at(4, -5) # => [nil, nil]

Для каждого Range спецификатора range, включает элементы в соответствии с range.begin и range.end:

  • Если оба range.begin и range.end неотрицательны и находятся в пределах диапазона (меньше self.size), включает элементы с индекса range.begin по range.end - 1 (если range.exclude_end?), или по range.end (иначе):

    a.values_at(1..2)  # => ["b", "c"]
    a.values_at(1...2) # => ["b"]
    
  • Если range.begin отрицателен и находится в пределах диапазона (больше или равно - self.size), считает назад от конца self:

    a.values_at(-2..3) # => ["c", "d"]
    
  • Если range.begin отрицателен и вне диапазона, выводит исключение:

    a.values_at(-5..3) # Raises RangeError.
    
  • Если range.end положителен и вне диапазона, дополняет возвращаемый массив nil элементами:

    a.values_at(1..5) # => ["b", "c", "d", nil, nil]
    
  • Если range.end отрицателен и находится в пределах диапазона, считает назад от конца self:

    a.values_at(1..-2) # => ["b", "c"]
    
  • Если range.end отрицателен и вне диапазона, возвращает пустой массив:

    a.values_at(1..-5) # => []
    

Указанные диапазоны могут быть в любом порядке и могут повторяться:

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

Указанные спецификаторы могут быть любой комбинацией индексов и диапазонов:

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

См. также: Методы извлечения.

zip(*другие_массивы) → новый_массив
zip(*другие_массивы) {|подмассив| ... } → 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 с набором other_arrays; возвращает новый массив подмассивов:

[0, 1].zip(['zero', 'one'], [:zero, :one])
# => [[0, "zero", :zero], [1, "one", :one]]

Возвращаемое значение:

  • Внешний массив имеет размер self.size.

  • Каждый подмассив имеет размер other_arrays.size + 1.

  • n-й подмассив содержит (в порядке):

    • n-й элемент self.

    • n-й элемент каждого из других массивов, если доступен.

Пример:

a = [0, 1]
zipped = a.zip(['zero', 'one'], [:zero, :one])
# => [[0, "zero", :zero], [1, "one", :one]]
zipped.size       # => 2 # Same size as a.
zipped.first.size # => 3 # Size of other arrays plus 1.

Когда другие массивы имеют такой же размер, как self, возвращаемые подмассивы представляют собой перестановку, содержащую ровно элементы всех массивов (включая self), без пропусков или добавлений:

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3]
c = [:c0, :c1, :c2, :c3]
d = a.zip(b, c)
pp d
# =>
[[:a0, :b0, :c0],
 [:a1, :b1, :c1],
 [:a2, :b2, :c2],
 [:a3, :b3, :c3]]

Когда один из других массивов меньше self, соответствующий подмассив дополняется nil элементами:

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2]
c = [:c0, :c1]
d = a.zip(b, c)
pp d
# =>
[[:a0, :b0, :c0],
 [:a1, :b1, :c1],
 [:a2, :b2, nil],
 [:a3, nil, nil]]

Когда один из других массивов больше self, пропускает его хвостовые элементы:

a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3, :b4]
c = [:c0, :c1, :c2, :c3, :c4, :c5]
d = a.zip(b, c)
pp d
# =>
[[:a0, :b0, :c0],
 [:a1, :b1, :c1],
 [:a2, :b2, :c2],
 [:a3, :b3, :c3]]

С блоком вызывает блок с каждым из других массивов; возвращает nil:

d = []
a = [:a0, :a1, :a2, :a3]
b = [:b0, :b1, :b2, :b3]
c = [:c0, :c1, :c2, :c3]
a.zip(b, c) {|sub_array| d.push(sub_array.reverse) } # => nil
pp d
# =>
[[:c0, :b0, :a0],
 [:c1, :b1, :a1],
 [:c2, :b2, :a2],
 [:c3, :b3, :a3]]

Для объекта в других_массивах, который не является массивом, формирует «другой массив» как object.to_ary, если он определён, или как object.each.to_a иначе.

См. также: Методы преобразования.

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

Spec-Zone.ru

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