класс Array
Публичные методы класса
# File activesupport/lib/active_support/core_ext/array/wrap.rb, line 37
def self.wrap(object)
if object.nil?
[]
elsif object.respond_to?(:to_ary)
object.to_ary || [object]
else
[object]
end
end Оборачивает свой аргумент в массив, если он не является уже массивом (или массивоподобным).
В частности:
-
Если аргумент
nilвозвращается пустой массив. -
В противном случае, если аргумент отвечает на
to_aryон вызывается, и возвращается его результат. -
В противном случае, возвращается массив с аргументом в качестве единственного элемента.
Array.wrap(nil) # => [] Array.wrap([1, 2, 3]) # => [1, 2, 3] Array.wrap(0) # => [0]
Этот метод аналогичен по назначению Kernel#Array, но есть некоторые отличия:
-
Если аргумент отвечает на
to_aryметод вызывается.Kernel#Arrayпереходит к попыткеto_aесли возвращаемое значениеnil, ноArray.wrapвозвращает массив с аргументом в качестве единственного элемента сразу. -
Если возвращаемое значение от
to_aryне является ниnilни объектомArray,Kernel#Arrayгенерирует исключение, в то время какArray.wrapэтого не делает, он просто возвращает значение. -
Он не вызывает
to_aдля аргумента, если аргумент не отвечает наto_aryон возвращает массив с аргументом в качестве единственного элемента.
Последний пункт легко объяснить на примере перечислителей:
Array(foo: :bar) # => [[:foo, :bar]]
Array.wrap(foo: :bar) # => [{:foo=>:bar}]
Также существует связанный идиоматический подход, использующий оператор splat:
[*object]
который возвращает [] для nil, но вызывает Array(object) в противном случае.
Различия с Kernel#Array описанные выше, применяются и к остальным object.
Общедоступные методы экземпляров
# File activesupport/lib/active_support/core_ext/object/deep_dup.rb, line 27 def deep_dup map(&:deep_dup) end
Возвращает глубокую копию массива.
array = [1, [2, 3]] dup = array.deep_dup dup[1][2] = 4 array[1][2] # => nil dup[1][2] # => 4
# File activesupport/lib/active_support/core_ext/array/extract_options.rb, line 22
def extract_options!
if last.is_a?(Hash) && last.extractable_options?
pop
else
{}
end
end Извлекает опции из набора аргументов. Удаляет и возвращает последний элемент в массиве, если это хэш, в противном случае возвращает пустой хэш.
def options(*args)
args.extract_options!
end
options(1, 2) # => {}
options(1, 2, a: :b) # => {:a=>:b}
# File activesupport/lib/active_support/core_ext/array/access.rb, line 66 def fifth self[4] end
Равно self[4].
%w( a b c d e ).fifth # => "e"
# File activesupport/lib/active_support/core_ext/array/access.rb, line 73 def forty_two self[41] end
Равно self[41]. Также известно как доступ к «reddit».
(1..42).to_a.forty_two # => 42
# File activesupport/lib/active_support/core_ext/array/access.rb, line 59 def fourth self[3] end
Равно self[3].
%w( a b c d e ).fourth # => "d"
# File activesupport/lib/active_support/core_ext/array/access.rb, line 10 def from(position) self[position, length] || [] end
Возвращает хвост массива с позиции position.
%w( a b c d ).from(0) # => ["a", "b", "c", "d"] %w( a b c d ).from(2) # => ["c", "d"] %w( a b c d ).from(10) # => [] %w().from(0) # => [] %w( a b c d ).from(-2) # => ["c", "d"] %w( a b c ).from(-10) # => []
# File activesupport/lib/active_support/core_ext/array/grouping.rb, line 60
def in_groups(number, fill_with = nil)
# size.div number gives minor group size;
# size % number gives how many objects need extra accommodation;
# each group hold either division or division + 1 items.
division = size.div number
modulo = size % number
# create a new array avoiding dup
groups = []
start = 0
number.times do |index|
length = division + (modulo > 0 && modulo > index ? 1 : 0)
groups << last_group = slice(start, length)
last_group << fill_with if fill_with != false &&
modulo > 0 && length == division
start += length
end
if block_given?
groups.each { |g| yield(g) }
else
groups
end
end Разбивает или итерирует массив на группы по number элементов, заполняя оставшиеся места значением fill_with, если не указано false.
%w(1 2 3 4 5 6 7 8 9 10).in_groups(3) {|group| p group}
["1", "2", "3", "4"]
["5", "6", "7", nil]
["8", "9", "10", nil]
%w(1 2 3 4 5 6 7 8 9 10).in_groups(3, ' ') {|group| p group}
["1", "2", "3", "4"]
["5", "6", "7", " "]
["8", "9", "10", " "]
%w(1 2 3 4 5 6 7).in_groups(3, false) {|group| p group}
["1", "2", "3"]
["4", "5"]
["6", "7"]
# File activesupport/lib/active_support/core_ext/array/grouping.rb, line 20
def in_groups_of(number, fill_with = nil)
if number.to_i <= 0
raise ArgumentError,
"Group size must be a positive integer, was #{number.inspect}"
end
if fill_with == false
collection = self
else
# size % number gives how many extra we have;
# subtracting from number gives how many to add;
# modulo number ensures we don't add group of just fill.
padding = (number - size % number) % number
collection = dup.concat(Array.new(padding, fill_with))
end
if block_given?
collection.each_slice(number) { |slice| yield(slice) }
else
collection.each_slice(number).to_a
end
end Разбивает или итерирует массив на группы по number элементов, заполняя оставшиеся места значением fill_with, если не указано false.
%w(1 2 3 4 5 6 7 8 9 10).in_groups_of(3) {|group| p group}
["1", "2", "3"]
["4", "5", "6"]
["7", "8", "9"]
["10", nil, nil]
%w(1 2 3 4 5).in_groups_of(2, ' ') {|group| p group}
["1", "2"]
["3", "4"]
["5", " "]
%w(1 2 3 4 5).in_groups_of(2, false) {|group| p group}
["1", "2"]
["3", "4"]
["5"]
# File activesupport/lib/active_support/core_ext/array/inquiry.rb, line 14 def inquiry ActiveSupport::ArrayInquirer.new(self) end
Оборачивает массив в объект ArrayInquirer, который предоставляет более удобный способ проверки его строкоподобного содержимого.
pets = [:cat, :dog].inquiry pets.cat? # => true pets.ferret? # => false pets.any?(:cat, :ferret) # => true pets.any?(:ferret, :alligator) # => false
# File activesupport/lib/active_support/core_ext/array/access.rb, line 45 def second self[1] end
Равно self[1].
%w( a b c d e ).second # => "b"
# File activesupport/lib/active_support/core_ext/array/access.rb, line 87 def second_to_last self[-2] end
Равно self[-2].
%w( a b c d e ).second_to_last # => "d"
# File activesupport/lib/active_support/core_ext/array/grouping.rb, line 91
def split(value = nil)
arr = self.dup
result = []
if block_given?
while (idx = arr.index { |i| yield i })
result << arr.shift(idx)
arr.shift
end
else
while (idx = arr.index(value))
result << arr.shift(idx)
arr.shift
end
end
result << arr
end Делит массив на один или несколько подмассивов на основе разделителя value или результата необязательного блока.
[1, 2, 3, 4, 5].split(3) # => [[1, 2], [4, 5]]
(1..10).to_a.split { |i| i % 3 == 0 } # => [[1, 2], [4, 5], [7, 8], [10]]
# File activesupport/lib/active_support/core_ext/array/access.rb, line 52 def third self[2] end
Равно self[2].
%w( a b c d e ).third # => "c"
# File activesupport/lib/active_support/core_ext/array/access.rb, line 80 def third_to_last self[-3] end
Равно self[-3].
%w( a b c d e ).third_to_last # => "c"
# File activesupport/lib/active_support/core_ext/array/access.rb, line 22
def to(position)
if position >= 0
take position + 1
else
self[0..position]
end
end Возвращает начало массива до позиции position.
%w( a b c d ).to(0) # => ["a"] %w( a b c d ).to(2) # => ["a", "b", "c"] %w( a b c d ).to(10) # => ["a", "b", "c", "d"] %w().to(0) # => [] %w( a b c d ).to(-2) # => ["a", "b", "c"] %w( a b c ).to(-10) # => []
# File activesupport/lib/active_support/core_ext/array/conversions.rb, line 91
def to_formatted_s(format = :default)
case format
when :db
if empty?
'null'
else
collect(&:id).join(',')
end
else
to_default_s
end
end Расширяет Array#to_s для преобразования коллекции элементов в список id, разделенных запятыми, если аргумент :db задан в качестве формата.
Blog.all.to_formatted_s(:db) # => "1,2,3" Blog.none.to_formatted_s(:db) # => "null" [1,2].to_formatted_s # => "[1, 2]"
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 40 def to_param collect(&:to_param).join '/' end
Вызывает to_param для всех своих элементов и объединяет результат с помощью слешей. Используется в url_for в Action Pack.
# File activesupport/lib/active_support/core_ext/object/to_query.rb, line 48
def to_query(key)
prefix = "#{key}[]"
if empty?
nil.to_query(prefix)
else
collect { |value| value.to_query(prefix) }.join '&'
end
end Преобразует массив в строку, подходящую для использования в строке запроса URL, используя заданное key в качестве имени параметра.
['Rails', 'coding'].to_query('hobbies') # => "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
# File activesupport/lib/active_support/core_ext/array/conversions.rb, line 59
def to_sentence(options = {})
options.assert_valid_keys(:words_connector, :two_words_connector, :last_word_connector, :locale)
default_connectors = {
:words_connector => ', ',
:two_words_connector => ' and ',
:last_word_connector => ', and '
}
if defined?(I18n)
i18n_connectors = I18n.translate(:'support.array', locale: options[:locale], default: {})
default_connectors.merge!(i18n_connectors)
end
options = default_connectors.merge!(options)
case length
when 0
''
when 1
"#{self[0]}"
when 2
"#{self[0]}#{options[:two_words_connector]}#{self[1]}"
else
"#{self[0...-1].join(options[:words_connector])}#{options[:last_word_connector]}#{self[-1]}"
end
end Преобразует массив в предложение с запятыми, где последний элемент соединён союзом.
Вы можете передать следующие опции, чтобы изменить стандартное поведение. Если вы передадите ключ опции, который не существует в списке ниже, будет выброшено исключение ArgumentError.
Опции
-
:words_connector- Символ или слово, используемое для объединения элементов в массивах с двумя или более элементами (по умолчанию: “, ”). -
:two_words_connector- Символ или слово, используемое для объединения элементов в массивах с двумя элементами (по умолчанию: “ и ”). -
:last_word_connector- Символ или слово, используемое для объединения последнего элемента в массивах с тремя или более элементами (по умолчанию: “, и ”). -
:locale- Еслиi18nдоступен, вы можете установить локаль и использовать опции соединителя, определенные в пространстве имен 'support.array' в соответствующем файле словаря.
Примеры
[].to_sentence # => "" ['one'].to_sentence # => "one" ['one', 'two'].to_sentence # => "one and two" ['one', 'two', 'three'].to_sentence # => "one, two, and three" ['one', 'two'].to_sentence(passing: 'invalid option') # => ArgumentError: Unknown key: :passing. Valid keys are: :words_connector, :two_words_connector, :last_word_connector, :locale ['one', 'two'].to_sentence(two_words_connector: '-') # => "one-two" ['one', 'two', 'three'].to_sentence(words_connector: ' or ', last_word_connector: ' or at least ') # => "one or two or at least three"
Использование опции :locale:
# Given this locale dictionary: # # es: # support: # array: # words_connector: " o " # two_words_connector: " y " # last_word_connector: " o al menos " ['uno', 'dos'].to_sentence(locale: :es) # => "uno y dos" ['uno', 'dos', 'tres'].to_sentence(locale: :es) # => "uno o dos o al menos tres"
# File activesupport/lib/active_support/core_ext/array/conversions.rb, line 181
def to_xml(options = {})
require 'active_support/builder' unless defined?(Builder)
options = options.dup
options[:indent] ||= 2
options[:builder] ||= Builder::XmlMarkup.new(indent: options[:indent])
options[:root] ||= if first.class != Hash && all? { |e| e.is_a?(first.class) }
underscored = ActiveSupport::Inflector.underscore(first.class.name)
ActiveSupport::Inflector.pluralize(underscored).tr('/', '_')
else
'objects'
end
builder = options[:builder]
builder.instruct! unless options.delete(:skip_instruct)
root = ActiveSupport::XmlMini.rename_key(options[:root].to_s, options)
children = options.delete(:children) || root.singularize
attributes = options[:skip_types] ? {} : { type: 'array' }
if empty?
builder.tag!(root, attributes)
else
builder.tag!(root, attributes) do
each { |value| ActiveSupport::XmlMini.to_tag(children, value, options) }
yield builder if block_given?
end
end
end Возвращает строку, представляющую массив в формате XML, вызывая to_xml для каждого элемента. Коллекции Active Record делегируют своё представление в XML этому методу.
Ожидается, что все элементы будут отвечать на to_xml, в противном случае будет возбуждено исключение.
Корневой узел отражает имя класса первого элемента во множественном числе, если все элементы принадлежат одному типу и это не Hash:
customer.projects.to_xml
<?xml version="1.0" encoding="UTF-8"?>
<projects type="array">
<project>
<amount type="decimal">20000.0</amount>
<customer-id type="integer">1567</customer-id>
<deal-date type="date">2008-04-09</deal-date>
...
</project>
<project>
<amount type="decimal">57230.0</amount>
<customer-id type="integer">1567</customer-id>
<deal-date type="date">2008-04-15</deal-date>
...
</project>
</projects> В противном случае корневым элементом является “objects”:
[{ foo: 1, bar: 2}, { baz: 3}].to_xml
<?xml version="1.0" encoding="UTF-8"?>
<objects type="array">
<object>
<bar type="integer">2</bar>
<foo type="integer">1</foo>
</object>
<object>
<baz type="integer">3</baz>
</object>
</objects> Если коллекция пуста, корневым элементом по умолчанию является “nil-classes”:
[].to_xml <?xml version="1.0" encoding="UTF-8"?> <nil-classes type="array"/>
Чтобы гарантировать осмысленный корневой элемент, используйте опцию :root:
customer_with_no_projects.projects.to_xml(root: 'projects') <?xml version="1.0" encoding="UTF-8"?> <projects type="array"/>
По умолчанию имя узла для дочерних элементов корневого узла — root.singularize. Вы можете изменить его с помощью опции :children.
Хэш options передаётся вниз по цепочке:
Message.all.to_xml(skip_types: true)
<?xml version="1.0" encoding="UTF-8"?>
<messages>
<message>
<created-at>2008-03-07T09:58:18+01:00</created-at>
<id>1</id>
<name>1</name>
<updated-at>2008-03-07T09:58:18+01:00</updated-at>
<user-id>1</user-id>
</message>
</messages> # File activesupport/lib/active_support/core_ext/array/access.rb, line 38 def without(*elements) self - elements end
Возвращает копию массива без указанных элементов.
people = ["David", "Rafael", "Aaron", "Todd"] people.without "Aaron", "Todd" => ["David", "Rafael"]
Примечание: Это оптимизация `Enumerable#without`, которая использует `Array#-` вместо `Array#reject` для повышения производительности.
© 2004–2018 David Heinemeier Hansson
Licensed under the MIT License.