Rubyデータ型 チートシート

cheatsheet

目的別 Rubyデータ型 操作早見表

🔢 数値 (Numeric)

整数、浮動小数点数、有理数、複素数を扱います。

目的 メソッド/演算子 説明とコード例
生成 リテラル, `to_i` 整数を直接記述するか、他の型から変換します。
num1 = 123
num2 = "456".to_i
num3 = 78.9.to_i # 小数点以下切り捨て
p [num1, num2, num3] #=> [123, 456, 78]
算術演算 `+`, `-`, `*`, `/`, `%`, `**` 加算、減算、乗算、除算(整数除算)、剰余、べき乗を行います。
a = 10
b = 3
p a + b  #=> 13
p a - b  #=> 7
p a * b  #=> 30
p a / b  #=> 3 (整数除算)
p a % b  #=> 1 (剰余)
p a ** b #=> 1000 (べき乗)
比較 `<`, `<=`, `==`, `>=`, `>`, `<=>` 大小関係や等価性を比較します。`<=>`は比較結果を-1, 0, 1で返します。
p 5 < 10   #=> true
p 5 == 5   #=> true
p 5 >= 10  #=> false
p 5 <=> 10 #=> -1
p 5 <=> 5  #=> 0
p 10 <=> 5 #=> 1
ビット演算 `&`, `|`, `^`, `~`, `<<`, `>>` ビット単位のAND, OR, XOR, NOT, 左シフト, 右シフトを行います。
a = 5  # 0101
b = 3  # 0011
p a & b  #=> 1   (0001)
p a | b  #=> 7   (0111)
p a ^ b  #=> 6   (0110)
p ~a     #=> -6  (2の補数)
p a << 1 #=> 10  (1010)
p a >> 1 #=> 2   (0010)
偶数/奇数判定 `even?`, `odd?` 整数が偶数か奇数かを判定します。
p 4.even? #=> true
p 5.even? #=> false
p 4.odd?  #=> false
p 5.odd?  #=> true
繰り返し `times`, `upto`, `downto`, `step` 指定回数、指定範囲での繰り返し処理を行います。
3.times { |i| print i, " " } #=> 0 1 2
puts

2.upto(5) { |i| print i, " " } #=> 2 3 4 5
puts

5.downto(2) { |i| print i, " " } #=> 5 4 3 2
puts

1.step(10, 3) { |i| print i, " " } #=> 1 4 7 10
puts
目的 メソッド/演算子 説明とコード例
生成 リテラル, `to_f` 浮動小数点数を直接記述するか、他の型から変換します。
f1 = 3.14
f2 = "1.618".to_f
f3 = 5.to_f
p [f1, f2, f3] #=> [3.14, 1.618, 5.0]
算術演算 `+`, `-`, `*`, `/`, `%`, `**` 整数と同様の演算を行いますが、結果は通常Floatになります。
a = 10.0
b = 3.0
p a / b #=> 3.3333333333333335
比較 `<`, `<=`, `==`, `>=`, `>`, `<=>` 整数と同様に比較しますが、浮動小数点数の精度に注意が必要です。
p 0.1 + 0.2 == 0.3 #=> false (精度問題)
p (0.1 + 0.2).round(5) == 0.3.round(5) #=> true (丸めて比較)
丸め処理 `round`, `ceil`, `floor`, `truncate` 四捨五入、切り上げ、切り捨て、0方向への切り捨てを行います。
f = 3.14159
p f.round    #=> 3
p f.round(2) #=> 3.14
p f.ceil     #=> 4
p f.floor    #=> 3
p f.truncate #=> 3

f_neg = -3.14159
p f_neg.round    #=> -3
p f_neg.ceil     #=> -3
p f_neg.floor    #=> -4
p f_neg.truncate #=> -3
特殊な値の判定 `nan?`, `infinite?` 非数 (NaN) か、無限大 (+/- Infinity) かを判定します。
p (0.0 / 0.0).nan?       #=> true
p (1.0 / 0.0).infinite?  #=> 1 (正の無限大)
p (-1.0 / 0.0).infinite? #=> -1 (負の無限大)
p 1.0.infinite?          #=> nil
目的 メソッド/演算子 説明とコード例
生成 `Rational()`, `to_r` 分子と分母を指定するか、他の数値型から変換します。
r1 = Rational(1, 2)
r2 = 0.5.to_r
r3 = 3.to_r
p [r1, r2, r3] #=> [(1/2), (1/2), (3/1)]
リテラル `r` を使うこともできます (Ruby 2.1+)
r4 = 1/2r
r5 = 0.5r
p [r4, r5] #=> [(1/2), (1/2)]
算術演算 `+`, `-`, `*`, `/`, `**` 有理数同士や他の数値型との間で正確な演算を行います。
r1 = 1/2r
r2 = 1/3r
p r1 + r2 #=> (5/6)
p r1 * 3  #=> (3/2)
p r1 / 0.5 #=> (1/1)
比較 `<`, `<=`, `==`, `>=`, `>`, `<=>` 他の数値型と同様に比較できます。
p 1/2r == 0.5 #=> true
p 1/3r < 1/2r #=> true
分子/分母取得 `numerator`, `denominator` 有理数の分子と分母を取得します。
r = 3/4r
p r.numerator   #=> 3
p r.denominator #=> 4
目的 メソッド/演算子 説明とコード例
生成 `Complex()`, `to_c` 実部と虚部を指定するか、他の数値型から変換します。
c1 = Complex(1, 2)  # 1 + 2i
c2 = 3.to_c         # 3 + 0i
c3 = "4+5i".to_c    # 4 + 5i
p [c1, c2, c3] #=> [(1+2i), (3+0i), (4+5i)]
リテラル `i` を使うこともできます (Ruby 2.1+)
c4 = 1+2i
c5 = 3i
p [c4, c5] #=> [(1+2i), (0+3i)]
算術演算 `+`, `-`, `*`, `/`, `**` 複素数同士や他の数値型との間で演算を行います。
c1 = 1+2i
c2 = 3-4i
p c1 + c2 #=> (4-2i)
p c1 * c2 #=> (11+2i)
p c1 / 2  #=> (0.5+1.0i)
比較 `==` 等価性のみ比較できます。大小比較はできません。
p 1+2i == Complex(1, 2) #=> true
p 1+2i == 1+3i          #=> false
実部/虚部取得 `real`, `imaginary` (`imag`) 複素数の実部と虚部を取得します。
c = 5+6i
p c.real      #=> 5
p c.imaginary #=> 6
p c.imag      #=> 6
共役複素数 `conjugate` 共役な複素数を返します。
c = 7+8i
p c.conjugate #=> (7-8i)
極形式関連 `abs`, `magnitude`, `arg`, `angle`, `phase`, `polar` 絶対値、偏角、極形式のタプル [絶対値, 偏角] を取得します。
c = 3+4i
p c.abs     #=> 5.0 (絶対値)
p c.arg     #=> 0.9272952180016122 (偏角ラジアン)
p c.polar   #=> [5.0, 0.9272952180016122]

📜 文字列 (String)

テキストデータを扱います。

目的 メソッド/演算子 説明とコード例
生成 `”`, `””`, `%q{}`, `%Q{}`, ヒアドキュメント シングルクォート (`”`, `%q{}`) は式展開や特殊文字シーケンス (`\n` など) を解釈しません。ダブルクォート (`””`, `%Q{}`, ヒアドキュメント) は解釈します。
name = "World"
s1 = 'Hello\n#{name}'
s2 = "Hello\n#{name}"
s3 = <<-EOS
Hello
#{name}
EOS
p s1 #=> "Hello\\n\#{name}"
p s2 #=> "Hello\nWorld"
puts s3
# Hello
# World
結合 `+`, `concat`, `<<` 文字列同士を結合します。`+` は新しい文字列を生成し、`concat` と `<<` は破壊的に(元の文字列を変更して)結合します。
s1 = "Hello"
s2 = " World"
s3 = s1 + s2
p s3 #=> "Hello World"
p s1 #=> "Hello" (変わらない)

s1.concat(s2)
p s1 #=> "Hello World" (変わる)

s1 << "!"
p s1 #=> "Hello World!" (変わる)
比較 `==`, `!=`, `<`, `<=`, `>`, `>=`, `<=>`, `eql?`, `equal?` 内容 (`==`, `eql?`) やオブジェクト同一性 (`equal?`)、辞書順 (`<`, `>`, `<=>`) で比較します。
s1 = "abc"
s2 = "abc"
s3 = "def"
s4 = s1

p s1 == s2  #=> true (内容が同じ)
p s1.eql?(s2) #=> true (内容が同じ)
p s1.equal?(s2) #=> false (オブジェクトは別)
p s1.equal?(s4) #=> true (オブジェクトが同じ)
p s1 < s3   #=> true (辞書順)
p s1 <=> s3 #=> -1
部分文字列取得 `[]`, `slice` インデックスや範囲、正規表現を使って部分文字列を取得します。
str = "Hello Ruby World"
p str[0]       #=> "H" (最初の文字)
p str[-1]      #=> "d" (最後の文字)
p str[6, 4]    #=> "Ruby" (6番目から4文字)
p str[6..9]    #=> "Ruby" (6番目から9番目まで)
p str[/Ruby/]  #=> "Ruby" (正規表現にマッチした部分)
p str.slice(0, 5) #=> "Hello"
部分文字列置換 `[]=` , `slice!` インデックスや範囲、正規表現で指定した部分を置換または削除(`slice!`)します。
str = "Hello Ruby World"
str[6, 4] = "Rails"
p str #=> "Hello Rails World"

str[/World/] = "Universe"
p str #=> "Hello Rails Universe"

removed = str.slice!(0, 6) # 破壊的に削除し、削除部分を返す
p removed #=> "Hello "
p str     #=> "Rails Universe"
検索 `include?`, `start_with?`, `end_with?`, `index`, `rindex`, `scan`, `match` 文字列が含まれるか、特定の文字列で始まる/終わるか、位置の検索、正規表現による全マッチ箇所の取得(`scan`)、最初のマッチ情報の取得(`match`)を行います。
str = "abracadabra"
p str.include?("cad")   #=> true
p str.start_with?("ab") #=> true
p str.end_with?("bra")   #=> true
p str.index('a')        #=> 0 (最初に見つかった'a'の位置)
p str.index('a', 1)     #=> 3 (1番目以降で最初に見つかった'a'の位置)
p str.rindex('a')       #=> 10 (最後に見つかった'a'の位置)
p str.scan(/a.r/)       #=> ["abr", "adr", "abr"] (マッチした全部分文字列の配列)
m = str.match(/a(.)r/)  # MatchDataオブジェクトを返す
p m[0] #=> "abr" (マッチ全体)
p m[1] #=> "b"   (キャプチャした部分)
置換 `sub`, `gsub`, `sub!`, `gsub!` 最初にマッチした部分 (`sub`) または全てマッチした部分 (`gsub`) を置換します。`!` 付きは破壊的メソッドです。ブロックを渡して動的な置換も可能です。
str = "apple banana apple"
p str.sub("apple", "orange") #=> "orange banana apple"
p str.gsub("apple", "orange") #=> "orange banana orange"
p str #=> "apple banana apple" (非破壊)

str.gsub!(/a/) { |s| s.upcase }
p str #=> "Apple bAnAnA Apple" (破壊的)
大文字/小文字変換 `upcase`, `downcase`, `capitalize`, `swapcase` 全て大文字、全て小文字、先頭のみ大文字、大文字小文字入れ替えを行います。それぞれ `!` 付きの破壊的メソッドもあります。
str = "hELLo wORLd"
p str.upcase     #=> "HELLO WORLD"
p str.downcase   #=> "hello world"
p str.capitalize #=> "Hello world"
p str.swapcase   #=> "HellO WorlD"
型変換 `to_i`, `to_f`, `to_r`, `to_c`, `to_sym` 整数、浮動小数点数、有理数、複素数、シンボルに変換します。
p "123".to_i   #=> 123
p "3.14".to_f #=> 3.14
p "2/3".to_r   #=> (2/3)
p "1+2i".to_c #=> (1+2i)
p "name".to_sym #=> :name
分割/結合 `split`, `join` (Arrayメソッド) 指定した区切り文字で文字列を分割して配列にします (`split`)。配列の要素を文字列で結合します (`join`)。
str = "apple,banana,orange"
arr = str.split(',')
p arr #=> ["apple", "banana", "orange"]

p arr.join(' | ') #=> "apple | banana | orange"
空白/改行処理 `strip`, `lstrip`, `rstrip`, `chomp`, `chop` 先頭と末尾 (`strip`)、先頭のみ (`lstrip`)、末尾のみ (`rstrip`) の空白文字を除去します。末尾の改行コード (`chomp`) または末尾の1文字 (`chop`) を除去します。それぞれ `!` 付きの破壊的メソッドもあります。
str = "  Hello World  \n"
p str.strip  #=> "Hello World"
p str.lstrip #=> "Hello World  \n"
p str.rstrip #=> "  Hello World"
p str.chomp  #=> "  Hello World  " (改行除去)
p "abc".chomp('c') #=> "ab" (指定文字除去)
p str.chop   #=> "  Hello World  " (最後の文字除去)
文字コード `encoding`, `encode`, `force_encoding` 現在のエンコーディング取得、指定エンコーディングへの変換、エンコーディング情報の強制変更を行います。
str_utf8 = "こんにちは"
p str_utf8.encoding #=> #<Encoding:UTF-8>

begin
  str_euc = str_utf8.encode(Encoding::EUC_JP)
  p str_euc.encoding #=> #<Encoding:EUC-JP>
  str_utf8_again = str_euc.encode(Encoding::UTF_8)
  p str_utf8_again == str_utf8 #=> true
rescue Encoding::UndefinedConversionError => e
  puts "変換エラー: #{e.message}"
end

# 不正なバイト列を持つ可能性のある文字列のエンコーディングを変更する場合
binary_data = "\x82\xA0\x82\xA2" # Shift_JIS の "あい"
binary_data.force_encoding(Encoding::Shift_JIS)
p binary_data.encoding #=> #<Encoding:Shift_JIS>
p binary_data.encode(Encoding::UTF_8) #=> "あい"
フォーマット `sprintf`, `%` 書式指定文字列に従って文字列をフォーマットします。
p sprintf("%s は %d 歳です。", "Alice", 30) #=> "Alice は 30 歳です。"
p "%s は %.2f kg です。" % ["Bob", 65.5]     #=> "Bob は 65.50 kg です。"
その他 `length`, `size`, `empty?`, `bytesize`, `reverse`, `center`, `ljust`, `rjust`, `lines`, `chars`, `codepoints` 文字数、空かどうかの判定、バイト数、逆順、中央/左/右寄せ、行/文字/コードポイント単位での処理など。
str = "Ruby"
p str.length   #=> 4
p str.empty?   #=> false
p str.bytesize #=> 4 (UTF-8の場合)
p str.reverse  #=> "ybuR"
p str.center(10, '*') #=> "***Ruby***"
p str.ljust(8)  #=> "Ruby    "
p str.rjust(8, '-') #=> "----Ruby"

multi_line = "line1\nline2"
p multi_line.lines #=> ["line1\n", "line2"]
p str.chars        #=> ["R", "u", "b", "y"]
p str.codepoints   #=> [82, 117, 98, 121]

📚 配列 (Array)

順序付けられた要素の集まりを扱います。異なる型の要素を混在させることができます。

目的 メソッド/演算子 説明とコード例
生成 `[]`, `Array.new`, `%w`, `%i` リテラル、`new`メソッド、文字列配列 (`%w`)、シンボル配列 (`%i`) で生成します。
arr1 = [1, "two", 3.0, :four]
arr2 = Array.new(3, "A") #=> ["A", "A", "A"]
arr3 = Array.new(3) { |i| i * i } #=> [0, 1, 4]
arr4 = %w(apple banana orange) #=> ["apple", "banana", "orange"]
arr5 = %i(red green blue)      #=> [:red, :green, :blue]
要素アクセス `[]`, `at`, `first`, `last`, `fetch` インデックスで要素を取得します。`fetch`は範囲外アクセス時にエラーを発生させるか、デフォルト値を返します。
arr = [:a, :b, :c, :d, :e]
p arr[0]    #=> :a
p arr.at(1) #=> :b
p arr[-1]   #=> :e
p arr.first #=> :a
p arr.last  #=> :e
p arr[1, 3] #=> [:b, :c, :d] (インデックス1から3要素)
p arr[1..3] #=> [:b, :c, :d] (インデックス1から3まで)

p arr.fetch(2) #=> :c
# p arr.fetch(10) #=> IndexError
p arr.fetch(10, "default") #=> "default"
p arr.fetch(10) { |i| "missing index #{i}" } #=> "missing index 10"
要素の追加/挿入 `push`, `<<`, `unshift`, `insert` 末尾に追加 (`push`, `<<`)、先頭に追加 (`unshift`)、指定位置に挿入 (`insert`) します。これらは破壊的メソッドです。
arr = [1, 2, 3]
arr.push(4, 5)
p arr #=> [1, 2, 3, 4, 5]
arr << 6
p arr #=> [1, 2, 3, 4, 5, 6]
arr.unshift(0)
p arr #=> [0, 1, 2, 3, 4, 5, 6]
arr.insert(3, "a", "b")
p arr #=> [0, 1, 2, "a", "b", 3, 4, 5, 6]
要素の削除 `pop`, `shift`, `delete`, `delete_at`, `compact`, `uniq`, `slice!`, `clear` 末尾 (`pop`)、先頭 (`shift`)、指定要素 (`delete`)、指定インデックス (`delete_at`)、`nil`要素 (`compact`)、重複要素 (`uniq`) を削除します。`slice!` は範囲指定で削除。`clear` は全要素削除。`!`なしの`compact`, `uniq`は非破壊的です。
arr = [1, 2, nil, 3, 2, nil, 4]
p arr.pop          #=> 4
p arr              #=> [1, 2, nil, 3, 2, nil]
p arr.shift        #=> 1
p arr              #=> [2, nil, 3, 2, nil]
p arr.delete(2)    #=> 2 (最初に見つかった2を削除し、削除した要素を返す)
p arr              #=> [nil, 3, 2, nil]
p arr.delete_at(1) #=> 3 (インデックス1を削除)
p arr              #=> [nil, 2, nil]
p arr.compact      #=> [2] (非破壊)
p arr              #=> [nil, 2, nil]
arr.compact!
p arr              #=> [2] (破壊的)

arr = [1, 2, 2, 3, 1]
p arr.uniq         #=> [1, 2, 3] (非破壊)
arr.uniq!
p arr              #=> [1, 2, 3] (破壊的)

arr = [10, 20, 30, 40, 50]
p arr.slice!(1, 2) #=> [20, 30] (削除した要素)
p arr              #=> [10, 40, 50]

arr.clear
p arr              #=> []
要素の置換 `[]=` , `fill` 指定したインデックスや範囲の要素を置き換えます。`fill`は指定範囲を指定値やブロックの結果で埋めます。
arr = [1, 2, 3, 4, 5]
arr[1] = "two"
p arr #=> [1, "two", 3, 4, 5]
arr[2..3] = ["a", "b", "c"]
p arr #=> [1, "two", "a", "b", "c", 5]

arr.fill(0, 1, 3) # インデックス1から3要素を0で埋める
p arr #=> [1, 0, 0, 0, "c", 5]

arr.fill { |i| i * 10 } # 全要素をインデックス*10で埋める
p arr #=> [0, 10, 20, 30, 40, 50]
結合・複製 `+`, `concat`, `*`, `dup`, `clone` 配列同士を結合 (`+`, `concat`)、配列を繰り返して結合 (`*`)、配列を複製 (`dup`, `clone`)します。`+`, `*` は新しい配列を返し、`concat` は破壊的です。`dup`は浅いコピー、`clone`は状態(frozenなど)もコピーします。
a1 = [1, 2]
a2 = [3, 4]
p a1 + a2     #=> [1, 2, 3, 4] (非破壊)
p a1.concat(a2) #=> [1, 2, 3, 4] (破壊的, a1が変わる)
p a2 * 3      #=> [3, 4, 3, 4, 3, 4]

a3 = [1, [2, 3]]
a4 = a3.dup
a5 = a3.clone
p a3.equal?(a4) #=> false
p a3[1].equal?(a4[1]) #=> true (内部配列は同じオブジェクト - 浅いコピー)

a3.freeze
# a4[0] = 100 # OK
# a5[0] = 100 # FrozenError (cloneはfreeze状態もコピー)
比較 `==`, `<=>` `==` は要素と順序が同じ場合に `true` を返します。`<=>` は辞書順で比較します。
p [1, 2, 3] == [1, 2, 3]   #=> true
p [1, 2, 3] == [1, 3, 2]   #=> false
p [1, 2] <=> [1, 3]      #=> -1
p [1, 2] <=> [1, 2]      #=> 0
p [1, 3] <=> [1, 2]      #=> 1
p [1, 2] <=> [1, 2, 3]   #=> -1
検索・選択 `include?`, `index`, `rindex`, `find`, `detect`, `select`, `filter`, `reject`, `grep`, `bsearch`, `bsearch_index` 要素の存在確認、インデックス検索、条件に合う最初の要素 (`find`/`detect`)、条件に合う全要素 (`select`/`filter`)、条件に合わない全要素 (`reject`)、パターンマッチ (`grep`)、二分探索 (`bsearch`/`bsearch_index` – ソート済配列用)を行います。
arr = [10, 20, 30, 40, 20, 50]
p arr.include?(30) #=> true
p arr.index(20)    #=> 1 (最初の20のインデックス)
p arr.rindex(20)   #=> 4 (最後の20のインデックス)
p arr.find { |x| x > 25 } #=> 30 (最初に見つかった要素)
p arr.select { |x| x.even? } #=> [10, 20, 30, 40, 20, 50]
p arr.reject { |x| x < 30 } #=> [30, 40, 50]

words = ["apple", "banana", "apricot"]
p words.grep(/ap/) #=> ["apple", "apricot"]
p words.grep(/a/) { |word| word.upcase } #=> ["APPLE", "BANANA", "APRICOT"]

sorted_arr = [1, 3, 5, 7, 9]
p sorted_arr.bsearch { |x| x >= 6 } #=> 7
p sorted_arr.bsearch_index { |x| x >= 6 } #=> 3
繰り返し処理 `each`, `map`, `collect`, `each_with_index`, `reverse_each` 各要素に対してブロックを実行 (`each`)、ブロックの戻り値で新しい配列を作成 (`map`/`collect`)、要素とインデックスを使って繰り返し (`each_with_index`)、逆順で繰り返し (`reverse_each`)。
arr = [1, 2, 3]
arr.each { |x| print x * 2, " " } #=> 2 4 6
puts

squares = arr.map { |x| x * x }
p squares #=> [1, 4, 9]
p arr     #=> [1, 2, 3] (非破壊)

arr.map! { |x| x * x } # 破壊的map (collect!も同じ)
p arr     #=> [1, 4, 9]

arr.each_with_index { |val, idx| puts "Index #{idx}: #{val}" }
# Index 0: 1
# Index 1: 4
# Index 2: 9

arr.reverse_each { |x| print x, " " } #=> 9 4 1
puts
ソート・順序 `sort`, `sort!`, `sort_by`, `sort_by!`, `reverse`, `reverse!`, `shuffle`, `shuffle!` 要素をソート (`sort`)、ブロックの評価結果でソート (`sort_by`)、順序を反転 (`reverse`)、要素をランダムに並び替え (`shuffle`) します。`!` 付きは破壊的メソッドです。
arr = [3, 1, 4, 1, 5, 9, 2]
p arr.sort #=> [1, 1, 2, 3, 4, 5, 9] (非破壊)
p arr      #=> [3, 1, 4, 1, 5, 9, 2]

words = ["caterpillar", "ant", "bee"]
p words.sort_by { |word| word.length } #=> ["ant", "bee", "caterpillar"]

p arr.reverse #=> [2, 9, 5, 1, 4, 1, 3] (非破壊)

arr.sort! # 破壊的ソート
p arr #=> [1, 1, 2, 3, 4, 5, 9]

arr.reverse! # 破壊的反転
p arr #=> [9, 5, 4, 3, 2, 1, 1]

p arr.shuffle #=> (ランダムな順序の配列)
p arr         #=> [9, 5, 4, 3, 2, 1, 1] (非破壊)
arr.shuffle!
p arr         #=> (ランダムな順序の配列 - 破壊的)
集合演算 `&`, `|`, `-`, `uniq` 積集合 (`&`)、和集合 (`|`)、差集合 (`-`) を計算します。和集合の結果は重複を含みますが、`uniq`と組み合わせることで重複を除去できます。
a1 = [1, 2, 3, 4]
a2 = [3, 4, 5, 6]
p a1 & a2 #=> [3, 4] (積集合)
p a1 | a2 #=> [1, 2, 3, 4, 5, 6] (和集合, 重複除去)
p (a1 + a2).uniq # 上と同じ
p a1 - a2 #=> [1, 2] (差集合 a1にありa2にないもの)
p a2 - a1 #=> [5, 6] (差集合 a2にありa1にないもの)
変換 `join`, `flatten`, `transpose`, `zip` 要素を文字列で結合 (`join`)、ネストした配列を平坦化 (`flatten`)、行列の転置 (`transpose` – 全要素が配列である必要あり)、複数の配列の要素をまとめる (`zip`)。
arr = [1, "two", 3.0]
p arr.join(" - ") #=> "1 - two - 3.0"

nested = [1, [2, 3], [4, [5]]]
p nested.flatten    #=> [1, 2, 3, 4, 5] (完全に平坦化)
p nested.flatten(1) #=> [1, 2, 3, 4, [5]] (1レベルのみ平坦化)

matrix = [[1, 2], [3, 4], [5, 6]]
p matrix.transpose #=> [[1, 3, 5], [2, 4, 6]]

a1 = [1, 2, 3]
a2 = [:a, :b, :c]
a3 = ["X", "Y"]
p a1.zip(a2, a3) #=> [[1, :a, "X"], [2, :b, "Y"], [3, :c, nil]]
その他 `length`, `size`, `count`, `empty?`, `sample`, `permutation`, `combination`, `rotate` 要素数、指定要素 or 条件に合う要素の数 (`count`)、空かの判定、ランダムな要素取得 (`sample`)、順列 (`permutation`)、組み合わせ (`combination`)、要素のローテーション (`rotate`)。
arr = [1, 2, 3, 2, 1]
p arr.length #=> 5
p arr.size   #=> 5
p arr.count(2) #=> 2 (要素2の数)
p arr.count { |x| x > 1 } #=> 3 (条件に合う要素の数)
p [].empty?  #=> true

p arr.sample     #=> (ランダムな1要素)
p arr.sample(2) #=> (ランダムな2要素の配列)

p [1, 2, 3].permutation.to_a
#=> [[1, 2, 3], [1, 3, 2], [2, 1, 3], [2, 3, 1], [3, 1, 2], [3, 2, 1]]
p [1, 2, 3].combination(2).to_a
#=> [[1, 2], [1, 3], [2, 3]]

a = [1, 2, 3, 4]
p a.rotate      #=> [2, 3, 4, 1] (非破壊)
p a.rotate(2)   #=> [3, 4, 1, 2]
p a.rotate(-1)  #=> [4, 1, 2, 3]
a.rotate!       # 破壊的ローテーション
p a             #=> [2, 3, 4, 1]

🔑 ハッシュ (Hash)

キーと値のペアによるコレクションです。キーは一意である必要があります。

目的 メソッド/演算子 説明とコード例
生成 `{}`, `Hash.new` リテラル (旧来の `=>` 形式、または Ruby 1.9+ のシンボルキー `key: value` 形式) や `new` メソッドで生成します。`Hash.new` でデフォルト値を設定できます。
h1 = { "a" => 100, "b" => 200 }
h2 = { a: 100, b: 200 } # シンボルキーの省略形
h3 = Hash.new
h4 = Hash.new(0) # 存在しないキーへのアクセス時に 0 を返す
p h4[:c] #=> 0
p h4      #=> {} (デフォルト値は代入されない)

h5 = Hash.new { |hash, key| hash[key] = "Default for #{key}" } # ブロックでデフォルト値を動的に設定
p h5[:d] #=> "Default for d"
p h5      #=> {:d=>"Default for d"} (ブロックは代入も行う)
要素アクセス `[]`, `fetch`, `values_at`, `dig` キーを使って値を取得します。`fetch` はキーが存在しない場合にエラーを発生させるか、デフォルト値を返します。`values_at` は複数のキーに対応する値を配列で返します。`dig` はネストしたハッシュや配列の要素を安全に取得します。
h = { a: 1, b: 2, c: 3 }
p h[:a]    #=> 1
p h[:d]    #=> nil (存在しないキー)

p h.fetch(:b) #=> 2
# p h.fetch(:d) #=> KeyError
p h.fetch(:d, "Not found") #=> "Not found"
p h.fetch(:d) { |k| "Key #{k} missing" } #=> "Key d missing"

p h.values_at(:a, :c, :d) #=> [1, 3, nil]

nested_h = { x: { y: { z: 10 } }, w: [1, 2] }
p nested_h.dig(:x, :y, :z) #=> 10
p nested_h.dig(:x, :y, :a) #=> nil
p nested_h.dig(:w, 0)      #=> 1
p nested_h.dig(:a, :b)    #=> nil
要素の追加/更新 `[]=`, `store`, `merge`, `merge!`, `update` キーを指定して値を代入 (`[]=`/`store`) します。他のハッシュと結合 (`merge`) します。`merge!` (`update`) は破壊的に結合します。重複キーがある場合、`merge` は引数のハッシュの値で上書きしますが、ブロックを渡して挙動を制御できます。
h = { a: 1, b: 2 }
h[:c] = 3
p h #=> {:a=>1, :b=>2, :c=>3}
h[:a] = 100
p h #=> {:a=>100, :b=>2, :c=>3}
h.store(:d, 4)
p h #=> {:a=>100, :b=>2, :c=>3, :d=>4}

h1 = { a: 1, b: 2 }
h2 = { b: 3, c: 4 }
h3 = h1.merge(h2)
p h3 #=> {:a=>1, :b=>3, :c=>4} (h2の値で上書き)
p h1 #=> {:a=>1, :b=>2} (非破壊)

h4 = h1.merge(h2) { |key, oldval, newval| oldval + newval }
p h4 #=> {:a=>1, :b=>5, :c=>4} (ブロックで結合処理を指定)

h1.merge!(h2) # update(h2) と同じ
p h1 #=> {:a=>1, :b=>3, :c=>4} (破壊的)
要素の削除 `delete`, `delete_if`, `keep_if`, `shift`, `reject!`, `select!`, `compact`, `compact!` 指定キーの要素を削除 (`delete`)、ブロックの条件に合う要素を削除 (`delete_if`/`reject!`)、条件に合わない要素を削除 (`keep_if`/`select!`)、最初のキー/値ペアを削除 (`shift`)、値が`nil`のペアを削除 (`compact`/`compact!`) します。`!`付きは破壊的メソッドです。
h = { a: 1, b: 2, c: 3, d: 4, e: nil }
p h.delete(:b) #=> 2 (削除した値を返す)
p h            #=> {:a=>1, :c=>3, :d=>4, :e=>nil}
p h.delete(:z) #=> nil (存在しないキー)
p h.delete(:z) { |k| "Not found: #{k}" } #=> "Not found: z"

h.delete_if { |key, value| value.odd? } # reject! も同様
p h #=> {:d=>4, :e=>nil}

h = { a: 1, b: 2, c: 3, d: 4, e: nil }
h.keep_if { |key, value| value.even? rescue false } # select! も同様 (nilはeven?を持たないのでrescue)
p h #=> {:b=>2, :d=>4}

h = { a: 1, b: 2, c: 3 }
p h.shift #=> [:a, 1] (削除したキーと値のペア)
p h       #=> {:b=>2, :c=>3}

h = { a: 1, b: nil, c: 3, d: nil }
p h.compact #=> {:a=>1, :c=>3} (非破壊)
h.compact!
p h       #=> {:a=>1, :c=>3} (破壊的)
キー/値の操作 `keys`, `values`, `key?`, `has_key?`, `include?`, `member?`, `value?`, `has_value?`, `invert`, `transform_keys`, `transform_values` 全キーの配列 (`keys`)、全値の配列 (`values`)、キーの存在確認 (`key?` など)、値の存在確認 (`value?` など)、キーと値を入れ替えたハッシュ (`invert`)、キー/値を変換した新しいハッシュ (`transform_keys`/`transform_values`) を取得します。それぞれ `!` 付きの破壊的メソッドもあります。
h = { a: 1, b: 2, c: 1 }
p h.keys   #=> [:a, :b, :c]
p h.values #=> [1, 2, 1]
p h.key?(:a) #=> true
p h.has_key?(:d) #=> false
p h.value?(2) #=> true
p h.has_value?(3) #=> false

p h.invert #=> {1=>:c, 2=>:b} (値が重複する場合、最後のものが残る)

h_upper_keys = h.transform_keys { |k| k.to_s.upcase }
p h_upper_keys #=> {"A"=>1, "B"=>2, "C"=>1} (非破壊)
h_squared_values = h.transform_values { |v| v * v }
p h_squared_values #=> {:a=>1, :b=>4, :c=>1} (非破壊)

h.transform_keys! { |k| k.to_s }
p h #=> {"a"=>1, "b"=>2, "c"=>1} (破壊的)
h.transform_values! { |v| v + 10 }
p h #=> {"a"=>11, "b"=>12, "c"=>11} (破壊的)
比較 `==` キーと値のペアが完全に一致する場合に `true` を返します。順序は問いません(Ruby 1.9以降)。
h1 = { a: 1, b: 2 }
h2 = { b: 2, a: 1 }
h3 = { a: 1, b: 99 }
p h1 == h2 #=> true
p h1 == h3 #=> false
繰り返し処理 `each`, `each_key`, `each_value`, `each_pair` キーと値のペア (`each`, `each_pair`)、キーのみ (`each_key`)、値のみ (`each_value`) に対してブロックを実行します。
h = { name: "Alice", age: 30 }
h.each { |key, value| puts "#{key}: #{value}" }
# name: Alice
# age: 30

h.each_key { |key| print key, " " } #=> name age
puts
h.each_value { |value| print value, " " } #=> Alice 30
puts
変換 `to_a`, `flatten`, `sort`, `sort_by` [キー, 値] の配列の配列に変換 (`to_a`)、キーと値を交互に含む配列に変換 (`flatten`)、キーでソートされた配列 (`sort`)、ブロックの評価結果でソートされた配列 (`sort_by`) を取得します。
h = { c: 3, a: 1, b: 2 }
p h.to_a #=> [[:c, 3], [:a, 1], [:b, 2]] (順序は挿入順または不定)

# Ruby 1.9+ では挿入順が保持されるため、to_a の結果は予測可能
# Ruby 1.8 では不定

p h.flatten #=> [:c, 3, :a, 1, :b, 2]

p h.sort #=> [[:a, 1], [:b, 2], [:c, 3]] (キーでソート)

h_str_keys = { "three" => 3, "one" => 1, "two" => 2 }
p h_str_keys.sort_by { |key, value| value } #=> [["one", 1], ["two", 2], ["three", 3]] (値でソート)
その他 `length`, `size`, `empty?`, `clear`, `default`, `default_proc` 要素数、空かの判定、全要素削除、設定されたデフォルト値の取得、デフォルト値を生成するブロックの取得。
h = { a: 1, b: 2 }
p h.length #=> 2
p h.empty? #=> false

h_def = Hash.new("N/A")
p h_def.default      #=> "N/A"
p h_def.default_proc #=> nil

h_proc = Hash.new { |hash, key| Time.now }
p h_proc.default      #=> nil
p h_proc.default_proc #=> #<Proc:...(lambda)>

h.clear
p h #=> {}
p h.empty? #=> true

✨ シンボル (Symbol)

文字列に似ていますが、イミュータブル(変更不可)で、同じシンボルは常に同じオブジェクトIDを持ちます。主にハッシュのキーやメソッド名など、識別子として使用されます。

目的 メソッド/演算子 説明とコード例
生成 `:`リテラル, `%s{}`, `to_sym`, `intern` コロン (`:`) を先頭につけるか、文字列から変換 (`to_sym`, `intern`) します。 `%s{}` リテラルもあります。
sym1 = :my_symbol
sym2 = :"symbol-with-hyphen"
sym3 = "dynamic_symbol".to_sym
sym4 = "another_symbol".intern
sym5 = %s{yet_another}

p [sym1, sym2, sym3, sym4, sym5]
#=> [:my_symbol, :"symbol-with-hyphen", :dynamic_symbol, :another_symbol, :yet_another]

p :my_symbol.object_id == :my_symbol.object_id #=> true (常に同じID)
str1 = "hello"
str2 = "hello"
p str1.object_id == str2.object_id #=> false (通常は異なるID)
比較 `==`, `===` 同じシンボルかどうかを比較します。`===` は `case` 文での使用が主です。
p :apple == :apple #=> true
p :apple == :orange #=> false

status = :success
result = case status
         when :success
           "OK"
         when :error
           "NG"
         else
           "Unknown"
         end
p result #=> "OK"
文字列変換 `to_s`, `id2name` シンボルを文字列に変換します。
sym = :user_name
str = sym.to_s
p str #=> "user_name"
p sym.id2name #=> "user_name"
全シンボル取得 `Symbol.all_symbols` 現在Rubyプロセス内に存在する全てのシンボルの配列を返します。(注意: 大量になる可能性があります)
p Symbol.all_symbols.length #=> (大きな数)
p Symbol.all_symbols.include?(:my_symbol) #=> true (上で生成したシンボルが含まれる)
その他 `length`, `size`, `empty?` シンボルに対応する文字列の長さを返します。`empty?` は `:””` のような空シンボルで `true` を返します。
sym = :hello
p sym.length #=> 5
p sym.size   #=> 5
p sym.empty? #=> false
p :"".empty? #=> true

↔️ 範囲 (Range)

開始値と終了値を持つ範囲を表します。`..` は終端を含み、`…` は終端を含みません。

目的 メソッド/演算子 説明とコード例
生成 `..`, `…`, `Range.new` リテラルまたは `new` メソッドで生成します。
range1 = 1..5   # 1, 2, 3, 4, 5 を含む
range2 = 1...5  # 1, 2, 3, 4 を含む (5を含まない)
range3 = 'a'..'d' # 'a', 'b', 'c', 'd' を含む
range4 = Range.new(10, 15, true) # 10...16 と同じ (第三引数が true で終端を含まない)

p range1.to_a #=> [1, 2, 3, 4, 5]
p range2.to_a #=> [1, 2, 3, 4]
p range3.to_a #=> ["a", "b", "c", "d"]
p range4.to_a #=> [10, 11, 12, 13, 14, 15]
無限範囲 (Ruby 2.6+)
inf_range1 = (1..)    # 1から無限大
inf_range2 = (..10)   # 無限小から10まで
inf_range3 = (1...nil) # 1から無限大 (終端なし)

p inf_range1.begin #=> 1
p inf_range1.end   #=> nil

p inf_range2.begin #=> nil
p inf_range2.end   #=> 10

# 無限範囲は to_a できない (無限ループになる)
# p inf_range1.to_a #=> Error
要素の確認 `include?`, `member?`, `cover?`, `===` 指定した要素が範囲内に含まれるか確認します。`include?`/`member?` は離散的な要素(整数や文字)に対して実際に列挙して確認します。`cover?` は開始値と終了値の間にあるかで判断します(高速だが、離散的でない場合やステップが考慮されない)。`===` は `case` 文で使われ、`cover?` と同様の挙動をします。
range = 1..10
p range.include?(5)  #=> true
p range.include?(11) #=> false
p range.member?(5)   #=> true (include? のエイリアス)

p range.cover?(5.5) #=> true (1 <= 5.5 <= 10 なので true)
# include? は整数範囲に対して整数しか確認しない
p range.include?(5.5) #=> false

range_excl = 1...10
p range_excl.include?(10) #=> false
p range_excl.cover?(10)   #=> false (1 <= 10 < 10 ではない)
p range_excl.cover?(9.9)  #=> true

num = 7
result = case num
         when 1..5
           "Low"
         when 6..10
           "High"
         else
           "Other"
         end
p result #=> "High"
繰り返し `each`, `step` 範囲内の要素に対してブロックを実行します。`step` で間隔を指定できます。
(1..5).each { |i| print i, " " } #=> 1 2 3 4 5
puts
('a'...'d').each { |c| print c, " " } #=> a b c
puts
(0..10).step(2) { |i| print i, " " } #=> 0 2 4 6 8 10
puts
端点の取得 `begin`, `end`, `first`, `last` 開始値、終了値を取得します。`first` は開始値と同じですが、引数で最初のN個の要素を取得できます。`last` は終了値と同じですが、引数で最後のN個の要素を取得できます(終端を含まない範囲では注意)。
range = 5..10
p range.begin #=> 5
p range.end   #=> 10
p range.first #=> 5
p range.last  #=> 10
p range.first(3) #=> [5, 6, 7]
p range.last(3)  #=> [8, 9, 10]

range_excl = 5...10
p range_excl.begin #=> 5
p range_excl.end   #=> 10
p range_excl.first #=> 5
p range_excl.last  #=> 9 (終端を含まないため最後の要素)
p range_excl.last(3) #=> [7, 8, 9]
その他 `size`, `exclude_end?`, `min`, `max` 範囲内の要素数 (`size` – 整数範囲など計算可能な場合のみ)、終端を含むかどうかの判定 (`exclude_end?`)、最小値 (`min`)、最大値 (`max`) を取得します。
range = 1..10
p range.size #=> 10
p range.exclude_end? #=> false
p range.min #=> 1
p range.max #=> 10

range_excl = 1...10
p range_excl.size #=> 9
p range_excl.exclude_end? #=> true
p range_excl.min #=> 1
p range_excl.max #=> 9

inf_range = (1..)
# p inf_range.size #=> nil (計算不能)
# p inf_range.max #=> nil (計算不能)
p inf_range.min #=> 1

✅ 真偽値 (TrueClass, FalseClass) と nil (NilClass) ❌

条件分岐などで使われる基本的なオブジェクトです。Rubyでは `false` と `nil` のみが偽 (falsey) で、それ以外(`0`, 空文字列 `””`, 空配列 `[]` などを含む)は全て真 (truthy) として扱われます。

目的 リテラル/演算子/メソッド 説明とコード例
リテラル `true`, `false`, `nil` 真、偽、無を表すオブジェクトです。
is_ok = true
is_error = false
no_value = nil

p true.class  #=> TrueClass
p false.class #=> FalseClass
p nil.class   #=> NilClass
論理演算 `&&`, `||`, `!`, `and`, `or`, `not` AND (`&&`, `and`)、OR (`||`, `or`)、NOT (`!`, `not`) を行います。`&&`/`||` と `and`/`or` は優先順位が異なります (`&&`/`||` の方が高い)。
p true && true   #=> true
p true && false  #=> false
p false || true  #=> true
p false || false #=> false
p !true          #=> false
p !false         #=> true
p !nil           #=> true (nilは偽なので否定すると真)
p !0             #=> false (0は真なので否定すると偽)

# 優先順位の違い
result1 = false && true || true # (false && true) || true => false || true => true
result2 = false and true || true # false and (true || true) => false and true => false
p result1 #=> true
p result2 #=> false

# || は左辺が真なら左辺の値を、偽なら右辺の値を返す (デフォルト値設定によく使う)
name = nil
display_name = name || "Guest"
p display_name #=> "Guest"

# && は左辺が偽なら左辺の値を、真なら右辺の値を返す (メソッド呼び出しのガードによく使う)
user = { name: "Alice" }
# user = nil
user_name = user && user[:name] # userがnilならnil, そうでなければuser[:name]
# Ruby 2.3+ の Safe Navigation Operator (&.) を使う方が簡潔
# user_name = user&.name
p user_name #=> "Alice" (userがnilならnil)
比較 `==` オブジェクトが `true`, `false`, `nil` そのものであるかを比較します。
value = true
p value == true #=> true

value = nil
p value == nil #=> true
nil判定 `nil?` オブジェクトが `nil` である場合に `true` を返します。全てのオブジェクトがこのメソッドを持ちます。
p nil.nil?   #=> true
p false.nil? #=> false
p 0.nil?     #=> false
p "".nil?    #=> false
文字列変換 `to_s` それぞれの文字列表現を返します。
p true.to_s  #=> "true"
p false.to_s #=> "false"
p nil.to_s   #=> "" (空文字列)

🔍 正規表現 (Regexp)

文字列のパターンマッチングに使用します。

目的 リテラル/メソッド/演算子 説明とコード例
生成 `/pattern/options`, `Regexp.new`, `%r{pattern}options` リテラル (`/ /`)、`new`メソッド、`%r{}` リテラルで生成します。オプション (`i`: 大文字小文字無視, `m`: `.`が改行にマッチ, `x`: パターン中の空白とコメント無視) を指定できます。
regex1 = /abc/i
regex2 = Regexp.new("^start", Regexp::IGNORECASE | Regexp::MULTILINE)
regex3 = %r{end$}

p regex1.class #=> Regexp
マッチング `match`, `=~`, `===` 文字列に対して正規表現がマッチするかどうかを調べます。`match` はマッチした場合 `MatchData` オブジェクトを、しない場合は `nil` を返します。`=~` はマッチした場合に開始位置のインデックスを、しない場合は `nil` を返します (特殊変数 `$`, `$&` なども設定します)。`===` は `case` 文で使われ、マッチすれば `true` を返します (`=~` と似ていますが、インデックスではなく真偽値を返します)。
str = "Hello Ruby World"
regex = /Ruby/

# matchメソッド
match_data = regex.match(str)
if match_data
  p match_data[0]      #=> "Ruby" (マッチ全体)
  p match_data.pre_match  #=> "Hello "
  p match_data.post_match #=> " World"
else
  p "No match"
end

# =~ 演算子
index = (regex =~ str)
if index
  p index #=> 6 (マッチ開始位置)
  p $&    #=> "Ruby" (最後にマッチした文字列 - 注意: グローバル変数)
else
  p "No match"
end
# 逆順 str =~ regex も可能
p str =~ /World/ #=> 11

# === 演算子 (case文)
result = case str
         when /Hello/
           "Starts with Hello"
         when /World$/
           "Ends with World"
         else
           "No specific pattern"
         end
p result #=> "Starts with Hello"
p (/Ruby/ === str) #=> true
Stringメソッド連携 `scan`, `split`, `sub`, `gsub` Stringクラスのメソッドに正規表現を渡して、検索、分割、置換を行います。 (詳細はStringのセクション参照)
str = "apple, banana; orange"
p str.scan(/\w+/)     #=> ["apple", "banana", "orange"]
p str.split(/[,;]\s*/) #=> ["apple", "banana", "orange"]
p str.sub(/banana/, "grape") #=> "apple, grape; orange"
p str.gsub(/[aeiou]/, '*') #=> "*ppl*, b*n*n*; *r*ng*"
正規表現情報 `source`, `options`, `encoding`, `named_captures` 正規表現の元となった文字列 (`source`)、オプションフラグ (`options`)、エンコーディング (`encoding`)、名前付きキャプチャグループの情報 (`named_captures`) を取得します。
regex = /^(?\d{3})-(?\d{4})/i
p regex.source   #=> "^(?<area>\\d{3})-(?<city>\\d{4})"
p regex.options  #=> 1 (Regexp::IGNORECASE)
p regex.encoding #=> #<Encoding:UTF-8> (環境による)
p regex.named_captures #=> {"area"=>[1], "city"=>[2]}

match = regex.match("123-4567")
p match[:area] #=> "123"
p match[:city] #=> "4567"
エスケープ `Regexp.escape`, `Regexp.quote` 文字列中の正規表現メタ文字(`*`, `+`, `?`, `.`, `(`, `)`, `[`, `{`, `|`, `^`, `$`, `\` など)をエスケープし、リテラルな文字列としてマッチするようにします。
str = "Find me at data[1]*?"
query = "data[1]*?"
escaped_query = Regexp.escape(query)
p escaped_query #=> "data\\[1\\]\\*\\?"

regex = Regexp.new(escaped_query)
p regex.match(str)[0] #=> "data[1]*?"

コメント

タイトルとURLをコピーしました