この前、数値オブジェクトの拡張メソッドをまとめたので、次は Array の Rails 便利メソッドをまとめました。
可読性を向上させる
from(position)
, to(position)
位置を指定して値を取り出せる。from
は引数の位置「から」、to
は引数の位置「まで」。
[0, 1, 2, 3].from(1) #=> [1, 2, 3]
[0, 1, 2, 3].to(2) #=> [0, 1, 2]
from
と同じことをしようとすると
[0, 1, 2, 3][1..-1] #=> [1, 2, 3]
[0, 1, 2, 3][1, 3] #=> [1, 2, 3]
という感じになるので、とても直観的。
second
, third
, fourth
, fifth
, forty_two
パッと見の通り、その位置の値を返す。Ruby に first
があるので、その続きですね。
[1, 2, 3].second #=> 2
[1, 2, 3].third #=> 3
(1..42).to_a.forty_two #=> 42
append
, prepend
append
は <<
のエイリアス、prepend
は unshift
のエイリアス。
ただのエイリアスだけど、これも直観的なので、個人的にはよく使います。
[0, 1, 2].append(3) #=> [0, 1, 2, 3]
[0, 1, 2].prepend(-1) #=> [-1, 0, 1, 2]
グループ分けする
in_groups_of(number, fill_with = nil)
与えた number の長さの配列にグループ化する。
「10 人を 3 人ずつの班に分ける」というような使い方ができる。
(1..10).to_a.in_groups_of(3) #=> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, nil, nil]]
デフォルトでは、要素数が number に足りない場合は nil
が追加されるが、引数で指定する事も出来る。
(1..10).to_a.in_groups_of(3, 'hoge') #=> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10, "hoge", "hoge"]]
# false を渡すと補完しなくなる
(1..10).to_a.in_groups_of(3, false) #=> [[1, 2, 3], [4, 5, 6], [7, 8, 9], [10]]
さらにブロックで処理も与えられる。
('A'..'J').to_a.in_groups_of(3, false) {|g| puts "#{g.first}班 : #{g}" }
# A班 : ["A", "B", "C"]
# D班 : ["D", "E", "F"]
# G班 : ["G", "H", "I"]
# J班 : ["J"]
in_groups(number, fill_with = nil)
与えた number の数にグループ化する。
「10 人を 3 つの班に分ける」というような使い方ができる。
(1..10).to_a.in_groups(3) #=> [[1, 2, 3, 4], [5, 6, 7, nil], [8, 9, 10, nil]]
(1..10).to_a.in_groups(2) #=> [[1, 2, 3, 4, 5], [6, 7, 8, 9, 10]]
この時、足りない要素数は 1 以内になるように分けてくれる。
また、同じように補完する値を指定可能。
(1..10).to_a.in_groups(3, 'hoge') #=> [[1, 2, 3, 4], [5, 6, 7, "hoge"], [8, 9, 10, "hoge"]]
(1..10).to_a.in_groups(3, false) #=> [[1, 2, 3, 4], [5, 6, 7], [8, 9, 10]]
ブロックも
('A'..'J').to_a.in_groups(3, false) {|e| puts "#{e.first}班 : #{e}" }
# A班 : ["A", "B", "C", "D"]
# E班 : ["E", "F", "G"]
# H班 : ["H", "I", "J"]
split(value = nil)
指定した値にマッチ or ブロックの結果が true になるところで配列を分割する。
(1..5).to_a.split(3) #=> [[1, 2], [4, 5]]
[1, 2, 'a', 4, 5].split {|a| a.kind_of?(String) } #=> [[1, 2], [4, 5]]
文字列に変換する
to_sentence(options = {})
要素を連結して、文字列に変換する。
その際、以下のオプションが指定できる
オプション | 説明 |
---|---|
words_connector |
要素を連結する際の文字列 |
two_words_connector |
配列の要素が 2 の場合の連結文字列 |
last_word_connector |
最後の要素を連結する際の文字列 |
locale |
I18n 対応、言語を指定出来る |
['A', 'B', 'C'].to_sentence #=> "A, B, and C"
# 言語の指定
['A', 'B', 'C'].to_sentence(locale: :ja) #=> "AとBとC"
# 連結する文字列の指定
['A', 'B', 'C'].to_sentence(words_connector: ' と ') #=> "A と B, and C"
['A', 'B', 'C'].to_sentence(words_connector: ' と ', last_word_connector: ' そして ') #=> "A と B そして C"
# 要素が 2 つの場合は two_words_connector を使う
['A', 'B'].to_sentence(words_connector: ' と ', last_word_connector: ' そして ') #=> "A and B"
['A', 'B'].to_sentence(two_words_connector: ' あと ') #=> "A あと B"
全部のオプションを指定してみる
ja:
support:
array:
words_connector: ' と '
two_words_connector: ' そして '
last_word_connector: ' 最後に '
('A'..'J').to_a.in_groups(4, false) {|g| puts "#{g.first}班 : #{g.to_sentence(locale: :ja)}" }
# A班 : A と B 最後に C
# D班 : D と E 最後に F
# G班 : G そして H
# I班 : I そして J
無理矢理(・・;
to_s(format = :default)
Numeric クラスで拡張されている事を紹介しましたが、Array クラスでも拡張されています。
ただ、format が :db
しかないのと、id
属性があるオブジェクトの配列にしか使えないのが残念。
User.all.to_a.to_s(:db) #=> "1,2,3,4,5,6,7,8"
このように id を ,
区切りで連結して返します。
to_param
, to_query
, to_xml(options = {})
左から URL のパス、クエリ、XML に変換した文字列を返す。
紹介しておいて何ですが、あんまり使い方が思いつかなかった。。。
まあ、ActionPack の Renderers
とか Redirect
で使われるているので、どちらかというと Rails 内で使うために用意されているのかな。ただ、ちょっとしたスクリプト書くときに便利かも。
%w(qiita.com pekepek items).to_param #=> "qiita.com/pekepek/items"
%w(Rails coding).to_query('hobbies') #=> "hobbies%5B%5D=Rails&hobbies%5B%5D=coding"
puts [{foo: 1, bar: 2}, {baz: 'hogehoge'}].to_xml
# <?xml version="1.0" encoding="UTF-8"?>
# <objects type="array">
# <object>
# <foo type="integer">1</foo>
# <bar type="integer">2</bar>
# </object>
# <object>
# <baz>hogehoge</baz>
# </object>
# </objects>
その他
self.wrap(object)
Kernel#Array
基本動作は同じだが、Range や Hash を引数にした場合に挙動が異なる。
# 引数が Array の場合
Array([1, 2, 3]) #=> [1, 2, 3]
Array.wrap([1, 2, 3]) #=> [1, 2, 3]
# Hash の場合
Array(a: 1, b: 2, c: 3) #=> [[:a, 1], [:b, 2], [:c, 3]]
Array.wrap(a: 1, b: 2, c: 3) #=> [{:a=>1, :b=>2, :c=>3}]
# Range の場合
Array(1..3) #=> [1, 2, 3]
Array.wrap(1..3) #=> [1..3]
ちゃんと配列にラップしてくれるメソッドという感じですね。
Rails 5 で追加されるメソッド
最後に Rails 5 で追加されるメソッドも紹介。
second_to_last
, third_to_last
last の続きが追加された...!!
[1, 2, 3].third_to_last #=> 1
[1, 2, 3].second_to_last #=> 2
without(*elements)
elements で指定した要素を除いた配列を返す。中身は Array#-
してるだけ。
[1, 2, 3].without(1, 2) #=> [3]
inquiry
元々 String#inquiry
はあったが、Array にも追加された。
hogehoge?
というメソッドが呼べるようになり、実際にメソッド名と同じ要素が合ったら true
を返す。
users = %w(pekepek pokopok).inquiry #=> ["pekepek", "pokopok"]
users.pekepek? #=> true
users.pokopok? #=> true
users.tom? #=> false
include?('pekepek')
とやっている事は同じですが、引数がないと見た目がすっきりしていいですね。
また、inquiry
を呼ぶと、any?
がオーバーライドされて、可変長引数を受け取れる様になります。元の any?
と同じように引数が一つでもマッチしたら true を返します。
users = %w(pekepek pokopok).inquiry
users.any?('pekepek', 'hogehoge') #=> true
users.any?('hogehoge', 'fugafuga') #=> false
これは結構使いどころ多そうですね。
以上が Array の拡張メソッドです!