概要
パーフェクトRubyを読んでいて便利だと思ったもの一覧です。
Array編
http://qiita.com/kidachi_/items/e9cb26c4e6cb36b70a1c
Hash編
http://qiita.com/kidachi_/items/651b5b5580be40ad047e
String編
http://qiita.com/kidachi_/items/7b355eb355b2d1390cf5
Enumerable
ArrayやHash、Rangeなど、「オブジェクトの集まり」を表現するクラスには
Enumerableがincludeされており、それら全てのクラスで活用できる。
繰り返し処理
each_with_index
配列のkeyとvalueを両方繰り返す。
> %w(Ruby Python Java).each_with_index do |value, key|
> puts "#{key}: #{value}"
> end
0: Ruby
1: Python
2: Java
reverse
末尾から順に繰り返す。
> %w(Ruby Python Java).reverse { |val| puts val }
=> ["Java", "Python", "Ruby"]
each_slice
要素をn個ずつ区切って繰り返す。
> %w(Ruby Python Java C Smalltalk Brainfuck).each_slice 2 do |a, b|
> p [a, b]
> end
["Ruby", "Python"]
["Java", "C"]
["Smalltalk", "Brainfuck"]
> %w(Ruby Python Java C Smalltalk Brainfuck).each_slice 4 do |a, b, c, d|
> p [a, b, c, d]
> end
["Ruby", "Python", "Java", "C"]
["Smalltalk", "Brainfuck", nil, nil] # 帳尻が合わなかった部分はnil
each_cons
n個の連続した要素を1つずつずらしながら繰り返す
> %w(Ruby Python Java C Smalltalk Brainfuck).each_cons 2 do |a, b|
> p [a, b]
> end
["Ruby", "Python"]
["Python", "Java"]
["Java", "C"]
["C", "Smalltalk"]
["Smalltalk", "Brainfuck"]
評価結果を配列で返却
map
元の配列の各要素を変換して、新しい配列をつくる
> %w(Ruby Python Java).map { |s| s.upcase }
=> ["RUBY", "PYTHON", "JAVA"]
※eachとの比較
> %w(Ruby Python Java).each {|s| p s.upcase}
"RUBY"
"PYTHON"
"JAVA"
=> ["Ruby", "Python", "Java"]
eachは、戻り値には変更はない。
条件確認
all?
配列の要素が全て真であればtrueを返す。
> [true, true, true].all?
=> true
> [true, true, false].all?
=> false
none?
配列の要素が全て偽であればtrueを返す。
> [false, false, false].none?
=> true
> [true, true, false].none?
=> false
any?
配列の要素のうち一つでも真であればtrueを返す。
> [true, true, false].any?
=> true
> [false, false, false].any?
=> false
one?
配列の要素のうち一つだけ真であればtrueを返す。
> [false, false, true].one?
=> true
> [false, false, false].one?
=> false
> [false, true, true].one?
=> false
条件確認*ブロック
all?, none?, any?, one?はそれぞれブロックを渡す事が出来る。
# 要素が全て整数ならtrue
> [1, 10, 100].all? {|v| v.is_a?(Integer)}
=> true
# 要素が全て文字列ならtrue
> [1, 10, 100].all? {|v| v.is_a?(String)}
=> false
> ["Ruby", "Python", "Java"].all? {|v| v.is_a?(String)}
=> true
部分的な要素の取得
grep
各要素に対してgrepをかけ、マッチする要素を取得する。
# 正規表現にマッチする要素を取得
> %w(Ruby Python Java).grep(/y/)
=> ["Ruby", "Python"]
# 指定の型にマッチする要素を取得
> ["Ruby", "Python", "Java", 1, 10, 100].grep(String)
=> ["Ruby", "Python", "Java"]
> ["Ruby", "Python", "Java", 1, 10, 100].grep(Integer)
=> [1, 10, 100]
detect
戻り値が最初に真になった要素を取得
> %w(Ruby Python Java C Smalltalk Brainfuck).detect { |s| s.include?("y") }
=> "Ruby"
select
戻り値が真になった要素を全て取得。
> %w(Ruby Python Java C Smalltalk Brainfuck).select { |s| s.include?("y") }
=> ["Ruby", "Python"]
reject
戻り値が真になった要素以外を全て取得。
> %w(Ruby Python Java C Smalltalk Brainfuck).reject { |s| s.include?("y") }
=> ["Java", "C", "Smalltalk", "Brainfuck"]
take
先頭から任意の数の要素を取得。
> %w(Ruby Python Java C Smalltalk Brainfuck).take(3)
=> ["Ruby", "Python", "Java"]
drop
先頭から任意の数の要素をスキップしたものを取得。
> %w(Ruby Python Java C Smalltalk Brainfuck).drop(3)
=> ["C", "Smalltalk", "Brainfuck"]
take_while
ブロックが最初に偽を返すまでの要素を取得。
> %w(Ruby Python Java C Smalltalk Brainfuck).take_while { |s| s.include?("y") }
=> ["Ruby", "Python"]
drop_while
ブロックが最初に偽を返してからそれより後の要素を取得。
> %w(Ruby Python Java C Smalltalk Brainfuck).drop_while { |s| s.include?("y") }
=> ["Java", "C", "Smalltalk", "Brainfuck"]
畳み込み演算
inject
直前のブロックの戻り値が入った変数と、現在の要素が入った変数二つを利用して演算できる。
> [1, 2, 3, 4].inject(0) { |result, num| result + num }
=> 10 # 0 +1 + 2 + 3 + 4
第一引数には初期値(上記では0)を設定可能。
初期値を省略すると、先頭の要素が初期値として用いられる。
> [1, 2, 3, 4].inject { |result, num| result + num }
=> 10 # 1 + 2 + 3 + 4
繰り返しの度に呼び出すメソッドをシンボルで受け取ることも可能。
> [1, 2, 3, 4].inject(:+)
=> 10
> [1, 2, 3, 4].inject(:*)
=> 24
繰り返しとオブジェクトの更新
each_with_object
要素を繰り返しながら、オブジェクトを更新していき、最終的に行き着いた値が戻り値となる。
引数には、初期値となるオブジェクトを渡す。
> %w(Ruby Python Java).each_with_object({}) do |name, result|
> p result
> result[name] = name.length
> end
{}
{"Ruby"=>4}
{"Ruby"=>4, "Python"=>6}
=> {"Ruby"=>4, "Python"=>6, "Java"=>4}
要素のグルーピング
group_by
特定の条件に基づいて要素をグルーピングする。
ブロックを評価した結果がkeyとなるハッシュが返却される。
> ["Ruby", 1.0, "Python", 1000, 2.5, "Java"].group_by { |v| v.class }
=> {String=>["Ruby", "Python", "Java"], Float=>[1.0, 2.5], Fixnum=>[1000]}
partition
ブロックの戻り値が真か偽かによって二つのグループに分けた、新しい配列を返却する。
> ["Ruby", 1.0, "Python", 1000, 2.5, "Java"].partition { |v| v.is_a?(String) }
=> [["Ruby", "Python", "Java"], [1.0, 1000, 2.5]]
最小値と最大値
min, max, minmax
> range = (1..5)
> range.max
=> 5
> range.min
=> 1
> range.minmax
=> [1, 5]
min_by, max_by, minmax_by
ブロックで評価した結果の値で比較する。
(「何の最小値/最大値か」を決める事が出来る)
> lang = %w(Ruby Python Java C)
> lang.min_by { |s| s.length }
=> "C"
> lang.max_by { |s| s.length }
=> "Python"
> lang.minmax_by { |s| s.length }
=> ["C", "Python"]
ソート
sort, sort_by
> lang = %w(Ruby Python Java C)
# アルファベット順
> lang.sort
=> ["C", "Java", "Python", "Ruby"]
# 要素の長さ(1)
> lang.sort { |a, b| a.length <=> b.length }
=> ["C", "Java", "Ruby", "Python"]
# 要素の長さ(2)
> lang.sort_by { |str| str.length }
=> ["C", "Java", "Ruby", "Python"]
sort_byは、各要素に対して1度しかメソッド呼び出し(今回は.length)を行わないため、sortより高速。