Open9

Rubyのメソッドあれこれ(備忘録)

うーさんうーさん

Ruby Silver取得に向けてメソッドを備忘録としてスクラップに残しました。
情報に誤りがありましたら、やんわりとご指摘いただければ幸いです。

うーさんうーさん

【Array】

配列について

オブジェクト参照と配列操作の挙動

a = [1, 2, 3]
b = [1, 3, 5]
c = a  # c は a が参照している配列 [1, 2, 3] を参照
a = b & c  # a は新しい配列 [1, 3] を参照

p a  # => [1, 3]
p b  # => [1, 3, 5]
p c  # => [1, 2, 3]
  • aに新しいオブジェクトを代入すると、aは新しいオブジェクトを参照する
  • cは変わらず元のオブジェクトを参照する
a = [1, 2, 3]
c = a  # c は a を参照
a << 4  # a に 4 を追加

p a  # => [1, 2, 3, 4]
p c  # => [1, 2, 3, 4]
  • cが参照するaそのものの要素、内容を変更すると、その変更はcに反映される

Range

  • [1..10]
    • 1から10までを含む
    • 結果: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
  • [1...10]
    • 1から9まで(10は含まない)
    • 結果: [1, 2, 3, 4, 5, 6, 7, 8, 9]
  • [1....10]
    • 構文エラー
p (1..10).to_a  # => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
p (1...10).to_a # => [1, 2, 3, 4, 5, 6, 7, 8, 9]
# p (1....10).to_a は構文エラー

可変長引数(配列展開)

  • 可変長引数は、アスタリスク(*)を使って定義
def favorite(*k_pop)
  puts "#{k_pop.join('と')}が推しです!"
end

favorite('BTS')  # => BTSが推しです!
favorite('BTS', 'ルセラ') # =>BTSとルセラが推しです!
favorite('BTS', 'ルセラ', 'にゅじ') # =>BTSとルセラとにゅじが推しです!
  • 配列を展開して引数として渡しすこともできる
def favorite(*k_pop)
  puts "#{k_pop.join('と')}が推しです!"
end

groups = ['BTS', 'ルセラ', 'にゅじ']
favorite(*groups)  # => BTSとルセラとにゅじが推しです!

メソッドあれこれ

each_slice

指定された数字ごとに配列を分割する

arr = (1..30).to_a
container = []

arr.each_slice(7) do |i|
  container << i
end

p container.length
# このコードは7個に区切って、配列に分割される。
# [1..7],[8..14][15..21][22..28][29,30]の要素がcontainerに入っていて、lengthは5になる。

each_cons

指定された数字ごとに要素を取り出し配列で分割する。また、1ずつ前に進む。

(1..10).each_cons(3) {|arr| p arr }

# <実行結果>
# [1, 2, 3]
# [2, 3, 4]
# [3, 4, 5]
# [4, 5, 6]
# [5, 6, 7]
# [6, 7, 8]
# [7, 8, 9]
# [8, 9, 10]
このコードは、3個に区切って、配列に分割される。
[1..3],[2..5][3..6][4..7][5..8]の要素

delete

selfから引数の要素を削除。削除した要素を返す。⭐️破壊的

numbers = [1, 2, 3, 2, 4, 2]
puts numbers.delete(2) # => 2
puts numbers  # =>  [1, 3, 4]

flatten(flatten!)

新しい配列を返す。ネストされた配列が解消されて一次元の配列になる。

puts [1, [2, [3, 4]], 5].flatten  # => [1, 2, 3, 4, 5]

reverse(reverse!)

文字列の文字順を逆にする。

shift

配列の最初の要素を取り出し、その要素を返す。⭐️破壊的

unshift

配列の先頭に新しい要素を追加。引数が指定されてなかったら何もしない。⭐️破壊的

pop

配列の最後の要素を取り出し、その要素を返す。⭐️破壊的

push

配列の最後に新しい要素を追加。引数が指定されてなかったら何もしない。⭐️破壊的

array = [2, 3, 4]

# Shift
puts array.shift  # => 2
puts array        # => [3, 4]

# Unshift
array.unshift(1)
puts array        # => [1, 3, 4]

# Pop
puts array.pop    # => 4
puts array        # => [1, 3]

# Push
array.push(5)
puts array        # => [1, 3, 5]

# Reverse
array.reverse!
puts array        # => [5, 3, 1]

sort(sort!)

通常は昇順ソート。
{ |a, b | b <=> a } というブロックになると、降順ソート。


compact(compact!)

selfからnilを取り除く。


select/filter

与えられたブロックが真の値を返す要素の配列を返す。

numbers = [1, 2, 3, 4, 5]

# Array#select
puts numbers.select { |number| number.even? }  # => [2, 4]

# Array#filter
puts numbers.filter { |number| number.even? }  # => [2, 4]

product

レシーバの配列と引数で与えられた配列(複数可)のそれぞれから要素を1 個ずつとって配列とし,それらのすべての配列を要素とする配列を返す。

[1, 2].product([3, 4])

# 実行結果
# [[1, 3], [1, 4], [2, 3], [2, 4]]

Array#transpose

レシーバーの配列から行と列を入れ替えた配列を作成し返す。

[[1, 3],
 [1, 4],
 [2, 3],
 [2, 4]
].transpose

# 実行結果
# [[1, 1, 2, 2], [3, 4, 3, 4]]

group_by(&:itself)

ary = [1, 1, 1, 2, 3, 3]
p ary.group_by(&:itself)
{1=>[1, 1, 1], 2=>[2], 3=>[3, 3]}

combination

組み合わせ(順序なし、重複なし)

# to_a
> [1,2,3].combination(2).to_a
=> [[1, 2], [1, 3], [2, 3]]
うーさんうーさん

Hash

オブジェクト生成

空のHashオブジェクトを生成するにはHash({}), {}, Hash.new

オプション引数

  • メソッドの呼び出し時に省略可能で、デフォルト値が設定されている引数のこと
def greet(name:, greeting: "こんにちは")
  puts "#{greeting}, #{name}!"
end

greet(name: "太郎")  # => こんにちは、太郎 :デフォルトの挨拶を使用
greet(name: "花子", greeting: "おはよう")  #=> おはよう、花子 : カスタムの挨拶を使用

可変長引数

  • **をつける。メソッドに渡される引数の数が不定の場合に使用。
  • 任意の数の引数をキーと値のペアとして渡すことができる。
def person(**attributes)
  attributes.each do |key, value|
    puts "#{key}: #{value}"
  end
end

person(name: "太郎", age: 30, city: "神戸")

# name: 太郎
# age: 30
# city: 神戸

メソッドあれこれ

each

  • ブロックパラメーターはArrayとして渡される。
  • ブロックに対して各キーと値のペアを配列として渡すため。[key, valie]
  • |k, v|のように二つのパラメーターを使用すると、配列が自動的に分割されてkにキー、vに配列が渡される。
h.each {|k, v| puts "#{k}: #{v}" }  # キーと値を別々に受け取る
h.each {|arr| puts "#{arr[0]}: #{arr[1]}" }  # 配列として受け取る
  • Ruby の他の繰り返し処理(例:Enumerable#each_with_index)とも一貫性あり

default_proc

存在しないキーが参照されたときに実行されるカスタムブロックを設定または無効にするためのもの

h= {}
h.default_proc= procdo|hash, key|
    hash[key]= case
                    when (key% 15).zero?"FizzBuzz"
                    when (key% 5).zero?"Buzz"
                    when (key% 3).zero?"Fizz"
                else
                    key
                end
end

p h[1]  # => 1
p h[2]  # => 2
p h[3]  # => "Fizz"
p h[5]  # => "Buzz"
p h[15] # => "FizzBuzz"

h.default_proc = nil
p h[16] # => nil
# default_proc が nil になったので `16=>16 が追加されていない`
p h     # => {1=>1, 2=>2, 3=>"Fizz", 5=>"Buzz", 15=>"FizzBuzz"}

Hash#default: 存在しないキーが参照されたときに返される固定のデフォルト値を設定するためのもの


key

引数を一つ受け取り、返却値は引数にあった値を持つキー。引数の値を持つキーがなければ、nilを返す

hash =  {pet: cat, family: mother}
p hash.key cat # =>:animal 
p hash.key dog #=> nil 

values

引数を受け取らない。返却値はレシーバの値を集めた配列。

hash = {pet: cat, family: mother}

p hash.values # =>[cat, mother] 

values_at

可変長引数を受け取る。返却時は引数に指定したキーの値を集めた配列。

hash =  {pet: cat, family: mother, hobby: basketball}
p hash.values_at(:pet, :hobby) # => [cat, basketball] 

[]

引数を一つ受け取る。返却値は引数にあったキーが持つ値。引数のキーがなければnilを返す。


member?

ハッシュがキーをもつか判断できる


to_a

ハッシュを[キー、値]のペアを要素とする配列に変換


update

ハッシュに新しいキーと値のペアを追加し、ハッシュ自体を更新。⭐️破壊的


clear

戻り値は空のハッシュ。⭐️破壊!


delete(:key)

レシーバからkeyの項目を削除する。⭐️破壊!


store

ハッシュに新しいキーと値のペアを追加するメソッド
指定されたキーがすでに存在する場合は、その値を新しい値で上書きする。
hash[key] = value という構文と同じ(Hash[])


merge

selfと引数のハッシュをマージし、新しいHashを返す。

うーさんうーさん

String

Stringについてあれこれ


chomp(chomp!)

末尾から改行コードを取り除く。
self の末尾から rs で指定する改行コードを取り除いた文字列を生成して返す。


chop(chop!)

文字列の最後の文字を取り除いた新しい文字列を生成して返す
文字列の終端が "\r\n" であればその 2 文字を取り除く


spilit

  • Ruby の文字列分割(String#splitメソッド)
    • 基本構文: string.split(pattern)
  • 分割パターンの違い:
    • 文字列を使用: "1;2:3;4".split(";|:")
      • 結果: ["1;2:3;4"]
      • ";|:" 全体が1つの区切り文字として扱われる
    • 正規表現を使用: "1;2:3;4".split(/;|:/)
      • 結果: ["1", "2", "3", "4"]
      • ; または : で分割される
  • 複数の区切り文字を指定する場合
    • 正規表現を使用する: /;|:/
    • 文字クラスも使える: /[;:]/
  • 注意!!
    • 文字列と正規表現では挙動が大きく異なる
    • 意図した分割を行うには適切なパターンの選択が重要
p "テヒョンイ-ジョングガ-ジミナ".split /(-)/

#( )があると、マッチしたものを含んだ結果を返す。
["テヒョンイ", "-", "ジョングガ", "-", "ジミナ"]

p "ナムジュナ,ホソガ,ユンギャ,ソクジニ".split(/,/)

["ナムジュナ", "ホソガ", "ユンギャ", "ソクジニ"]と分解。

stripe(stripe!)

文字列先頭と末尾の空白文字を全て取り除いた文字列を生成。
空白文字の定義" \t\r\n\f\v\0"

  • lstripeは先頭を取り除く
  • rstripeは末尾を取り除く

String#%

フォーマットされた文字列を返す。
フォーマットは"%d"%sなどの指示子
文字列"Hello"にフォーマットに必要な指示子が無いためそのまま出力される。


chars

レシーバのすべての文字の配列を返す。文字は1文字のも文字列で表現される


"hello".chars # => ["h", "e", "l", "l", "o"]

each_char

文字列の各文字に対して繰り返し。

"hello".each_char {|c| print c, ' ' }
h e l l o

gsub(gsub!)

パターンにマッチするすべての部分を置換した文字列を返す。

p 'abcdefg'.gsub(/def/, '!!')# => "abc!!g"

sub(sub!)

パターンにマッチする最初の部分を置換した文字列を返す。

str = 'hello world'
result = str.sub('o', '0')
puts result  # => "hell0 world"

replace

与えられた文字列でレシーバの内容を置き換える。⭐️破壊的

str = 'hello world'
str.replace('goodbye')
puts str  # => "goodbye"

slice

最初にマッチした部分文字列を返す。マッチしなかった場合はnilを返す。

["foo: abc", "bar: 100"].each do |i|
  p i.slice(/[0-9]+/)&.to_i
end

nil
100

to_i

先頭の文字から整数としての解析を試み、有効な数字ではなくなるまで解析を続ける。
文字列が有効な数字ではじまらない場合、0が返される。
デフォルトでは10進数として解析。他の基数(2から36まで)をパラメータで指定できる。

  • "42A7".to_i42を返す。
  • "42A7".to_i(16)は16進数0x42A7の値(10進数では17063)を返す

delete_prefix

与えられた文字列を先頭から削除した文字列を返す。


delete

引数で指定されたすべての文字を削除するため、"$foo$".delete("$")の評価結果は"foo"


scan

複数の一致する部分文字列を取り出すには、scan メソッドを使用する。
(最初に一致したものを取り出すのは slice

text = "hogepiyohogehoge"
matches = text.scan(/o../)
p matches  # => ["oge", "oho", "oge"]

うーさんうーさん

例外

def food(name)
  begin
    raise ArgumentError, "処理失敗!" if name.empty?
    puts "食べ物の名前は: #{name}"
  rescue ArgumentError => e
    puts "失敗してもうたがな: #{e.message}" # `e`は、キャッチした例外オブジェクトを参照する変数
  else
    puts "成功したら表示されまっせ"
  ensure
    puts "成功しても例外起きても表示されまっせ"
  end
end

# メソッドの呼び出し例
food('apple')
# =>食べ物の名前は: apple
# =>成功したら表示されまっせ
# =>成功しても例外起きても表示されまっせ

food("")
# => 失敗してもうたがな: 処理失敗!
# => 成功しても例外起きても表示されまっせ

例外あれこれ

  • 例外の発生
    • raise メソッドで例外を発生させる
    • 例: raise ArgumentError, "引数が不正です"
    • 引数なしの raiseRuntimeError を発生

  • 例外のキャッチ
    • begin...rescue...end 構文を使用
    • 例外クラスとメッセージは rescue => e で参照可能
    • rescue => ee は、キャッチした例外オブジェクトを参照する変数

  • rescue 節の動作
    • 例外クラス未指定: StandardError とそのサブクラスを捕捉
    • rescue StandardError => eStandardError とそのすべてのサブクラス(RuntimeError を含む)をキャッチ!
    • 例外クラス指定: 指定したクラスとそのサブクラスのみ
    • 複数の rescue 節で異なる例外を個別に処理可能

  • 例外オブジェクト
    • e.class: 例外のクラスを取得
    • e.message: 例外のメッセージを取得

  • else と ensure
    • else: 例外が発生しなかった場合に実行
    • ensure: 例外の有無に関わらず必ず実行

  • 例外の階層
    • StandardError は多くの一般的な例外のスーパークラス
    • SystemExit, NoMemoryError などの重大な例外は別階層

  • その他
    return: メソッドやブロックの実行を終了し、呼び出し元に制御を戻す。通常のメソッドの終了や結果の返却に使用。
    retry : 再度begin節の処理を実行する
うーさんうーさん

attr_reader

読み取りのみ

class Person
  attr_reader :name

  def initialize(name)
    @name = name
  end
end

person = Person.new('テヒョン')
puts person.name  # => 'テヒョン'
# person.name = 'ジョングク'  # これはエラーになる

attr_writer

書き込みのみ

class Person
  attr_writer :name

def initialize(name)
    @name = name
  end
end

person = Person.new('テヒョン')
person.name = 'ジョングク'  # => OK
# puts person.name # これはエラーになる

attr_accessor

読み書きOK

class Person
  attr_accessor :name

  def initialize(name)
    @name = name
  end
end

person = Person.new('テヒョン')
puts person.name  # => 'テヒョン'
person.name = 'ジョングク'
puts person.name # => 'ジョングク'
うーさんうーさん

演算子

  • 演算子|は、集合の和演算を返し、&は積演算を返す。
  • 和集合は重複を排除する。積演算は共通してるものだけを返す。
["a", 1] | ["b", 2]     # => ["a", 1, "b", 2]
["a", 1] & ["a", "b", 1, 2] # => ["a", 1]

  • 論理演算子||(論理和)は左辺の式がtrueの場合、右辺の評価は行わずに左辺の値を返す。
  • &&`(論理積)はfalseの場合、左辺で終了して評価を返す。左辺がtrueの場合は右辺の値を返す。
1 || nil # => 1 :右辺は評価されない
nil || 1 # => 1
1 && nil # => nil
nil && 1  # => nil :右辺は評価されない
puts ([] && "hello")        # =>  hello
puts (nil && "hello")       # =>  nil
puts ("world" && "hello")   # =>  hello
うーさんうーさん

IO/File

IOクラス

IO(Input/Output) クラス。入力および出力操作を扱うための基本クラス。

【メソッド】

  • eof? :end of file ? ポインタがファイルの終端にあるか確認。
  • rewind: ファイルポインタを先頭に戻す。
  • gets: 1行読み込み。
  • readlines: ファイルの現在位置から終端まで全ての行を読み込んで配列で返す。
    • 各要素は1行のテキスト。改行文字を含む。読み込み後、ポインタは終端に移動。
  • seek(offset, whence):ファイルポインタを指定した位置に移動。
    • offset: 移動するバイト数
    • whence:移動の起点

【ファイルポインタ】

ファイル内の現在の読み書き位置を表すカーソルのこと。

  • IO::SEEK_CUR: 現在のポインタ位置が起点
  • IO::SEEK_SET: ファイルの先頭が起点
  • IO::SEEK_END: ファイルの終端が起点

Fileクラス

IOクラスを継承している。ファイル操作に特化。
ファイルの読み書き、ファイル情報の取得、ファイル削除など。

【メソッド】

  • open: ファイルを開く。以下のオープンモードを指定して読み書きの方法を決める。
    • 'a': 追記書き込みモード/読み込み不可
    • 'a+': 読み込み + 追記/末尾に追記、読み込みは先頭から
    • 'w': 書き込み専用(上書き)/ 既存ファイルは空に、読み込み不可
    • 'w+': 読み込み + 書き込み(上書き )/ファイルを空にしてから操作
    • 'r': 読み込み専用 /デフォルトのモード
    • 'r+': 読み込み + 書き込み/既存内容を保持、読み書き可能
  • read: ファイルの内容を全て読み込み、文字列として返す
  • write: ファイルにデータを書き込む
  • chmod : 引数に指定したファイルのモードを変更
  • delete: 指定したファイルを削除。成功で削除数を返し、失敗でエラー表示。
  • dirname: パスのディレクトリ部分を返す
  • basename: パスのファイル名を返す
うーさんうーさん

Enumerable

inject /reduce

レシーバの要素に対して、引数で指定した処理を行う

  • 非破壊的メソッド
  • ブロックまたはシンボルで処理を指定可能
  • 配列操作の効率化とコードの簡潔化に貢献
  • 結果を1つの値に集約
  • 初期値の指定が可能

[1, 2, 3].inject(:+)# => 6
[1, 2, 3].inject(0) { |x, y| x + y }# => 6


collect/map

レシーバの要素に対して引数で指定した処理を行った結果を含む配列を返す

  • 非破壊的メソッド
  • ブロックまたはシンボルで処理を指定可能
  • 配列操作の効率化とコードの簡潔化に貢献
  • 新しい配列を返す
  • 元の配列は変更しない
[1, 2, 3].map(&:to_s) # => ["1", "2", "3"]
[1, 2, 3].collect { |n| n + 1 } # => [2, 3, 4]

&:メソッド名記法

  • { |item| item.メソッド名 } の省略形
  • 単一メソッド適用時に有用

find_all/select

条件に合う要素を全て集めて新しい配列を作る

numbers = [1, 2, 3, 4, 5]
numbers.select { |n| n.even? }  # => [2, 4]

detect/find

条件に合う最初の要素を見つける

条件を最初に満たした要素を返す。なければnil

numbers = [1, 2, 3, 4, 5]
numbers.detect { |n| n.even? }  #=>  2

grep

引数にマッチする要素だけを抽出。
引数に正規表現も使える。
マッチする要素がないと空の配列がかえる。

# 数字を含むものを抽出する
['a1', 'bb', 'c2', 'dd', '5e'].grep(/[0-9]/)
# => ["a1", "c2", "5e"]

# 大文字の英語を含むものがないので空の配列が返る
['a1', 'bb', 'c2', 'dd', '5e'].grep(/[A-Z]/)
=> []

take_while

{}ブロック内の式が falseになる手前の要素まで を返す。

# 3が出るまで抽出する
[1, 2, 3, 4, 5, 6].take_while { |i| i < 3 }
# => [1, 2]

drop_while

take_whileの反対で、{}ブロック内の式が falseになった以降の要素すべて を返す。

# 3が出たらそれ以降を抽出する
[1, 2, 3, 4, 5, 6]. drop_while { |i| i < 3 }
# => [3, 4, 5, 6]

group_by

{}ブロック内の式の 結果をキー、対応する要素の配列を値 とするハッシュを返す。

#奇数と偶数でグループ分けする
[1, 2, 3, 4, 5, 6].group_by { |i| i % 2 }
# => {1 => [1, 3, 5], 0 => [2, 4, 6]}

結果がboolになる式の場合はキーがtrue/falseになる。

sort_by

{}ブロック内の式の結果を <=> 演算子で比較し、昇順にソート

# 文字を昇順にソートする
p ["foo", "bar", "Baz", "Qux"].sort_by { |v| v.downcase }
# => ["bar", "Baz", "foo", "Qux"]

# こうすれば数字を降順にソートできる。元の値の符号を反転させて、大きな値ほど負の数になるため。
# 降順ソートですな
p [1, 5, 7, 2, 4, 9].sort_by { |v| v * -1 }
# => [9, 7, 5, 4, 2, 1]

any?

ブロックの戻り値がtrueになると繰り返しをその時点で止める


tally

値が同じ要素の数を含むハッシュを返す。
"cocoa".chars.tallyの評価結果は{"c"=>2, "o"=>2, "a"=>1}