класс Array
Объект Array представляет собой упорядоченную коллекцию объектов, индексированных целыми числами, называемых элементами; он представляет собой структуру данных «массив».
Элементом может быть любой объект (даже другой массив); элементы могут быть любой смесью объектов разных типов.
К важным структурам данных, использующим массивы, относятся:
Также существуют структуры данных, похожие на массивы:
-
Ассоциативный массив (см.
Hash). -
Директория (см.
Dir). -
Переменная окружения (см.
ENV).
Индексы массива
Индексация массивов начинается с 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, который преобразует объект в массив.
-
CSV::Table#to_a
-
Gem::List#to_a
-
Gem::NameTuple#to_a -
Gem::Platform#to_a -
Gem::RequestSet::Lockfile::Tokenizer#to_a -
Gem::SourceList#to_a -
Racc::ISet#to_a
-
Rinda::RingFinger#to_a
-
Ripper::Lexer::Elem#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?: Возвращает, содержит ли массив заданный объект. -
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: Вставляет заданные объекты в заданный смещение; не заменяет элементы. -
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: Возвращает сумму элементов, в соответствии с+или заданным блоком.
Методы класса
Исходный код
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/]
См. также: Методы для создания массива.
Исходный код
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, если первый аргумент — отрицательное целое число.
См. также: Методы для создания массива.
Исходный код
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.
См. также: Методы для создания массива.
Методы экземпляра публичного интерфейса
Исходный код
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).
См. также: Методы для объединения.
Исходный код
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}"
Исходный код
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]
См. также: Методы для объединения.
Исходный код
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).
См. также: Методы для объединения.
Исходный код
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]]
См. также: Методы присваивания.
Исходный код
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
См. также: Методы сравнения.
Исходный код
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?.
См. также: Методы сравнения.
Исходный код
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]
См. также: Методы извлечения.
Исходный код
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"]
См. также: Методы присваивания.
Исходный код
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]
См. также: Методы объединения.
Исходный код
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 пусто (независимо от переданных аргументов или блока).
См. также: Методы запросов.
Исходный код
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 пусто (независимо от переданных аргументов или блока).
См. также: Методы запросов.
Добавляет каждый аргумент в 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]]
См. также: Методы присваивания.
Исходный код
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; также см. Методы извлечения.
Исходный код
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#[]; также см. Методы извлечения.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
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.
Связанное: см. Методы для итерации.
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."
Связанное: см. Методы для удаления.
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
Связанное: см. Методы для удаления.
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.
Связанное: см. Методы для удаления.
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#-; см. также Методы для объединения.
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
Связанное: см. Методы для извлечения.
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) # => []
Связанное: см. Методы для извлечения.
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.
Связанное: см. Методы для извлечения.
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.
Связанное: см. Методы для итерации.
Исходный код
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.
Исходный код
static VALUE
rb_ary_empty_p(VALUE ary)
{
return RBOOL(RARRAY_LEN(ary) == 0);
} Возвращает true, если количество элементов в self равно нулю, false в противном случае.
Связанные методы: см. Methods for Querying.
Исходный код
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.
Исходный код
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.
Исходный код
# 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.
Исходный код
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.
При заданном блоке вызывается блок с каждым элементом self; возвращает новый массив, содержащий те элементы self, для которых блок возвращает истинное значение:
a = [:foo, 'bar', 2, :bam]
a.select {|element| element.to_s.start_with?('b') }
# => ["bar", :bam]
Без блока возвращает новый Enumerator.
Связанное: см. Способы извлечения.
При заданном блоке вызывается блок с каждым элементом self; удаляет из self те элементы, для которых блок возвращает false или nil.
Возвращает self если были удалены какие-либо элементы:
a = [:foo, 'bar', 2, :bam]
a.select! {|element| element.to_s.start_with?('b') } # => ["bar", :bam]
Возвращает nil если элементы не были удалены.
Без блока возвращает новый Enumerator.
Связанное: см. Способы удаления.
Источник
# 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]
Связанное: см. Способы запроса.
Источник
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!; см. также Способы преобразования.
Источник
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; см. также Способы присвоения.
Источник
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?.
Источник
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
Источник
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
Связанное: см. Способы запроса.
Возвращает нулевой индекс указанного элемента или 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.
Связанное: см. Способы запроса.
Исходный код
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"]
Связанное: см. Методы присваивания.
Исходный код
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 отрицательно и выходит за пределы диапазона.
Связанное: см. Методы присваивания.
Исходный код
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]"
Связанное: см. Методы преобразования.
Исходный код
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.
Связанное: см. Методы запроса.
Исходный код
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 при отсутствии аргументов.
Связанное: см. Методы объединения.
Исходный код
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"
Связанное: см. Методы преобразования.
Исходный код
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.
Связанное: см. Методы удаления.
Исходный код
# 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) # => []
Связанное: см. Методы извлечения.
Исходный код
static VALUE
rb_ary_length(VALUE ary)
{
long len = RARRAY_LEN(ary);
return LONG2NUM(len);
} Возвращает количество элементов в self:
[0, 1, 2].length # => 3 [].length # => 0
Связанное: см. Методы запроса.
При наличии блока вызывает блок с каждым элементом self; возвращает новый массив, элементы которого являются возвращаемыми значениями из блока:
a = [:foo, 'bar', 2]
a1 = a.map {|element| element.class }
a1 # => [Symbol, String, Integer]
Без блока возвращает новый Enumerator.
Связанное: collect!; см. также Методы преобразования.
При наличии блока, вызывает блок для каждого элемента self и заменяет элемент возвращаемым значением блока; возвращает self:
a = [:foo, 'bar', 2]
a.map! { |element| element.class } # => [Symbol, String, Integer]
Без блока возвращает новый Enumerator.
Связанно с: collect; см. также Методы для преобразования.
Исходный код
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"]
Связанно с: см. Методы для извлечения.
Исходный код
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"]
Связанно с: см. Методы для извлечения.
Исходный код
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"]
Связанно с: см. Методы для извлечения.
Исходный код
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
Связанно с: см. Методы для запросов.
Исходный код
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
Связанно с: см. Методы для запросов.
Исходный код
# File pack.rb, line 7 def pack(fmt, buffer: nil) Primitive.pack_pack(fmt, buffer) end
Форматирует каждый элемент в self в двоичную строку; возвращает эту строку. См. Упакованные данные.
Исходный код
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.
Связанные: Методы для итерации.
Исходный код
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; см. также Методы для удаления.
Добавляет указанные objects в начало self:
a = [:foo, 'bar', 2] a.unshift(:bam, :bat) # => [:bam, :bat, :foo, "bar", 2]
Связанные: Array#shift; см. также Методы для присваивания.
Исходный код
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]]
Связанные: см. Методы для объединения.
Исходный код
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]]
Связанные: см. Методы для присваивания.
Исходный код
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; см. также Методы для извлечения.
Исходный код
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.
Связанные: Методы для извлечения.
Исходный код
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.
Связанные: см. Методы для удаления.
Исходный код
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.
Связанные: см. Методы для объединения.
Исходный код
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.
Связанные: см. Способы комбинирования.
Заменяет элементы self элементами other_array, которые должны быть объектом, преобразуемым в массив ; объект, преобразуемый в массив; возвращает self.
a = ['a', 'b', 'c'] # => ["a", "b", "c"] a.replace(['d', 'e']) # => ["d", "e"]
Связанные: см. Методы присваивания.
Исходный код
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]
Связанные: см. Способы комбинирования.
Исходный код
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]
Связанные: см. Методы присваивания.
Исходный код
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.
Связанные: см. Методы итерирования.
Исходный код
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.
Связанные: см. Методы запроса.
Исходный код
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]
Связанные: см. Методы извлечения.
Исходный код
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]
Связанные: см. Методы присваивания.
Исходный код
# 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]
Связанные: см. Способы получения элементов.
Исходный код
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.
Связанные: см. Способы получения элементов.
Исходный код
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.
Связанные: см. Методы для удаления.
Исходный код
# File lib/shellwords.rb, line 251 def shelljoin Shellwords.join(self) end
Строит строку командной строки из списка аргументов array объединяя все элементы, экранированные для оболочки Bourne и разделенные пробелом.
Подробности см. в Shellwords.shelljoin.
Исходный код
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 пустой, возвращает новый пустой массив.
Связанные: см. Методы для удаления.
Исходный код
# 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 используется как генератор случайных чисел.
Связанные: см. Способы получения элементов.
Исходный код
# 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 используется как генератор случайных чисел.
Связанные: см. Методы присваивания.
Возвращает количество элементов в self:
[0, 1, 2].length # => 3 [].length # => 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.
Когда заданы два целочисленных аргумента 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]
См. также: Методы извлечения.
Исходный код
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"]
См. также: Методы удаления.
Исходный код
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 неопределён и может быть нестабильным.
См. также: Методы извлечения.
Исходный код
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 с отсортированными элементами на месте.
См. также: Методы присваивания.
Исходный код
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.
См. также: Методы присваивания.
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#+.
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.
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.
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.
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.
Возвращает новую строку, образованную вызовом метода inspect для каждого элемента массива:
a = [:foo, 'bar', 2] a.inspect # => "[:foo, \"bar\", 2]"
Связанное: см. Methods for Converting.
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.
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.
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.
Исходный код
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
См. также: Методы удаления.
Исходный код
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; см. также Методы присваивания.
Исходный код
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"]
См. также: Методы извлечения.
Исходный код
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.