この記事は「こんな書き方もあったな」というのを簡単に 復習 できるように作りました。そのため、実行結果が書いていなかったり、コード内で未定義の変数を使っていたりします。予めご了承ください。
間違い等ありましたら遠慮なくコメントください。
参考
たのしいRuby、高橋征義、後藤裕蔵著、 まつもとゆきひろ監修、SBクリエイティブ株式会社、第6版2019年
1. 基本
- 動的型付け言語なので、型を明示的に指定はしない
- オブジェクト指向型言語なので、データをオブジェクトで表現する
a = 3
b = "文字列"
- nil : nullのこと
- 条件ではnilとfalseを偽、それ以外を真としている
-
do end
で囲まれている部分をブロックと言う - 配列やハッシュに
*
を付けると、そのオブジェクトを展開することができる - Rubyではスネーク方式で命名する
- Rubyにおけるthenは省略可能
-
do end
を{ }
と書くこともできる -
b=a
としたとき、a
に破壊的な変更をするとb
も変わる。a.freeze
で防げる -
a.dup
でオブジェクトをコピー
2. 文字列
"文字列" #=> 文字列
%Q{ "がエスケープされる } #=> "がエスケープされる
'特殊文字をそのままにする'
%q| 'がエスケープされる | #=> 'がエスケープされる
"\n" #=> 改行
"\\n" #=> エスケープ
2.1 メソッド
2.1.1 非破壊的
x = 3
print "あいう", x , "\n" #=> あいう3
print "あいう#{x}\n" #=> あいう3
puts # 文字列の最後で改行
p # 型に合わせて表示、特殊文字もそのまま表示
pp # オブジェクトの構造に合わせて改行もしてくれる
printf("あいうえお") # C言語の`printf`とほぼ同じ
sprintf("あいうえお") # ただ文字列オブジェクトを作るだけ
format("あいうえお") # sprintfと同じ。%bなどで形式を指定する
s.to_sym # シンボルに変換
s.to_i # "32a".to_i => 32 "abc".to_i => 0
`コマンド` # コマンドの出力を文字列オブジェクトにする
s = "あいうえお"
s.length #=> 5
s.chars #=> ["あ","い","う","え","お"]
s.size # lengthと同じ
s.bytesize #=> 15
s[0] #=> あ
s[2,4] #=> うえお
s1 + s2
s1 << s2 # +とおなじ
"あいう" < "あいえ" # 不等号
s.freeze # 変更不可 sに格納されているオブジェクトが変更できないだけで、s自体に新たなオブジェクトを代入することは可能。破壊的なメソッドとかは使えなくなる
# # frozen-string-literal :trueとコメントを書くことで、そのスクリプト内の全ての文字列に.freezeを付けたことになる
2.1.2 非破壊的
s.index("a") # 何文字目か(0始まり、左から探索) "1a1a1" => 1
s.rindex("a") # 右から探索 "1a1a1" => 3
s.include?("a") # 含むか
s.replace("a") # => "a"に置き換え
2.1.3 !
を付けると破壊的になる
s.delete("ac") # 与えられた文字列を全て削除する "abcabc" => "bb"
s.delete_prefix("a") # 先頭の文字列を削除する "abcabc" => "bcabc"
s.chop # 末尾を1文字削る "abcd" => "abc"
s.chomp # 末尾の改行を削る
s.strip # 先頭と末尾の空白を取り除く
s.upcase # "aBc" => "ABC"
s.downcase # "aBc" => "abc"
s.swapcase # "aBc" => "AbC"
s.capitalize # 先頭だけ大文字 "aBc" => "Abc"
s.tr("a","A") # 置き換え "aBc" => "ABc"
s.tr("ac","CA") # "aBc" => "CBA"
s.tr("a-e","A-E") # "aBc" => "ABC"
2.2 ヒアドキュメント (筆者の理解が足りてないので簡単に)
<<"EOB" # これは"あいうえお"と同じ
あいうえお
EOB
<<-"EOB" # 区切り文字の行頭の空白文字とタブ文字を無視
あいうえお
EOB
<<~"EOB" # 行頭の空白文字とタブ文字を無視
あいうえお
EOB
3. シンボル
- 文字列と似たオブジェクト
- 「シンボル」という型があると考えればよい
- 以下2つは同じもの
x = :a
x = :"a"
-
x.to_s
: 文字列に変換
4. 配列
- Rubyは0始まり
4.1 配列の生成
a = Array.new #=> []
a = Array.new(3) #=> [nil, nil, nil]
a = Array.new(3,0) #=> [0, 0, 0]
a = %w(I like basketball) #=> ["I", "like", "basketball"]
a = %i(i like basketball) #=> [:i, :like, :basketball]
a = "I,like,basketball".split(',') #=> ["I", "like", "basketball"]
a = [1, 3, "hello", 2]
4.2 配列の参照
- 配列の要素数を超えたインデックスを参照した場合はエラーではなく
nil
が返る - 負の値のインデックス
-n
を参照した場合は、配列の最後からn番目を返してくれる
a = ["a","b","c","d","e", "f"]
a[0] #=> "a"
# 配列の要素数を超えたインデックスを参照した場合は、最後の要素を指定したことになる
a[0..2] #=> ["a", "b", "c"]
a[-1..1] # 負の数はだめ => []
a[2,3] #=> ["c", "d", "e"]
a[-2,10] # 配列の最後から最初に戻ることは無い => ["e", "f"]
a.values_at(0,2,3) #=> ["a", "c", "d"]
a[0] = 12 # => [12, "b", "c", "d", "e", "f"]
a[1..2] = [4,5,6,7,8] #=> ["a", 4, 5, 6, 7, 8, "d", "e", "f"]
a[2,3] = [4,5,6,7,8] #=> ["a", "b", 4, 5, 6, 7, 8, "f"]
a[2,0] = [4,5,6,7,8] #=> ["a", "b", 4, 5, 6, 7, 8, "c", "d", "e", "f"]
a.each do |i|
puts i
end
a.each_with_index do |value, index|
pp [value,index] # indexが何番目か
end
4.3 メソッド
先頭要素を | 末尾要素を | |
---|---|---|
加える(破壊的) | unshift | push |
取り出す(破壊的) | shift | pop |
参照する | first | last |
4.3.1 破壊的メソッド
a.unshift(3) # ["a","b","c"] => [3,"a","b","c"]
a.push(3) # ["a","b","c"] => ["a","b","c",3]
a << 3 # pushと同じ
a.shift #=> "a" ["a","b","c"] => ["b","c"]
a.shift(2) #=> ["a","b"] ["a","b","c"] => ["c"]
a.pop #=> "c" ["a","b","c"] => ["a","b"]
a.concat(b) # 配列の結合 +=と同じ
a.delete("a") # ["a","b","c"] => ["b","c"]
a.delete_at(1) # ["a","b","c"] => ["a","c"]
a.delete_if { |i| i == "a" } # ["a","b","c"] => ["b","c"]
a.fill("d") # 置き換え ["a","b","c"] => ["d","d","d"]
a.fill("d",2) # ["a","b","c"] => ["a","b","d"]
a.fill("x",1,2) # ["a","b","c","d","e","f"] => ["a","x","x","d","e","f"]
a.fill("x",3..4) # ["a","b","c","d","e","f"] => ["a","b","c","x","x","f"]
4.3.2 非破壊的メソッド
a = ["a","b","c","d","e","f"]
b = ["d","e","f","g","h","i",]
a.size #=> 6
a & b # 積集合 ["d", "e", "f"]
a | b # 和集合 "a", "b", "c", "d", "e", "f", "g", "h", "i"]
a + b # "|"と似ているが、重複を許す ["a", "b", "c", "d", "e", "f", "d", "e", "f", "g", "h", "i"]
a - b # ["a", "b", "c"]
a.first
a.last
a.sort_by { |i| i.size } # 昇順
a.zip(b,c){ |i,j,k| puts i+j+k }
a.find{|x| x<3} # 真になる最初の要素を返す。見つからない時はnil [2,3,4] => 2
a.detect{|x| x<3} # findと同じ
["a", "b", "c", "b"].tally #=> {"a"=>1, "b"=>2, "c"=>1}
# 出てくる回数を数える
h = {}
[:a, :b, :c].tally(h)
[:a, :b, :d].tally(h) # h => {:a=>2, :b=>2, :c=>1, :d=>1}
4.3.3 !
をつけると破壊的になる
a.compact # nilを除く
a.select { |i| i>3 } # 条件に当てはまるものだけにする
a.reject { |i| i>3 } # 条件に当てはまるものを除く
a.uniq # 重複を無くす
a.map { |i| i*2 } # 置き換え
a.collect { |i| i*2 } # mapと同じ
a.flatten # 入れ子になった配列を1つの配列にする
a.reverse # 順番を逆にする
a.sort # 昇順
a.sort { |i, j| i.size <=> j.size }
a.slice(3) # a[3]
a.slice(3..5) # a[3..5]
a.slice(3,2) # a[3,2]
4.3.4 初期化
a = Array.new(3,[0,0,0]) # 3つの要素が全て同じオブジェクトになる
a = Array.new(3) do # このようにすれば、違うオブジェクトになる
[0,0,0]
end
a = Array.new(3) { |i| i**2 }
5. ハッシュ
key1 == key2 && key1.eql?(key2)
のときのみ同じキーだと判断される
eql?
は内容が同じなら、別オブジェクトでもtrue
を返すメソッド
5.1 基本
h = {:basket=>5, "soccer"=>11, 9=>"baseball"}
h = {basket: 5, soccer: 11} # シンボルをキーにする場合
h = Hash.new
h = Hash.new(1) # 登録されてないキーを指定された時のデフォルト値
h = Hash.new do |hash, key| # デフォルト値をこのようにも定義できる
hash[key] = key.length
end
h.fetch(:basket,1) # 登録していないキーならデフォルト値を返す
h[:basket]
h["soccer"]
h[9]
h[:basker] = 10
h.each do |key, value|
puts key, value
end
h = {
:sports => {:basket => 5, :baseball => 9},
:music => {:solo => 1, :duo => 2}
}
# 以下4つは同じ。キーに持ってるかを判定
h.key?(:basket)
h.has_key?(:basket)
h.include?(:basket)
h.member?(:basket)
h.value?(5)
h.has_value?(5)
# キーの数
h.size
h.length
h.empty?
5.2 破壊的メソッド
h.delete(:basket)
h.delete(:no) do |key|
puts key # キーが存在しないときの処理
end
h.delete_if do |key, value| # 1つも削除されない時は元のハッシュを返す
key == :soccer
end
g = h
h.clear # gもhも{}になる
5.3 !をつけると破壊的メソッド
h.reject do |key, value| # 1つも削除されない時はnilを返す
key == :soccer
end
h1.merge(h2) # 2つのハッシュをくっつける
6 コメント
#コメント
=begin
コメント
=end
7 条件
- 偽 :
false
とnil
- 比較演算子 :
> < == !=
-
===
: 左辺がStringやInteger→==
,左辺がRegexp→=~
,左辺がクラスオブジェクト→右辺が左辺のインスタンスかどうかを判定してくれる
-
- 論理演算子 :
&& || !
7.1 メソッド
- 語尾に
?
を付ける -
empty?
: 文字列や配列が空ならtrue
-
nil?
:nil
ならtrue
-
blank?
:empty?
||nil?
7.2条件文
if a >= 10 then
puts "aは10以上"
elsif a >= 0 then
puts "aは0以上"
else
puts "aは0未満"
end
puts "aは0" if a == 0
unless a >= 10 then
puts "aは10以上ではない"
end
puts "aは0でない" unless a == 0
// case文は`===`で判定してる
case a
when 1, 2, 3 then
puts "aは1or2or3"
when 4 then
puts "aは2"
when 5, 6 then
puts "aは5or6"
else
puts "それ以外"
end
// aの所属するクラスでも分岐できる
case a
when String then
puts "aはString"
when Numeric then
puts "aはNumeric"
else
puts "それ以外"
end
## 7.3 条件演算子(三項演算子)
max = a>b ? a : b
# Rubyにおいて条件文は、最後に評価した値を返す関数のようなもの
x = if a > b
a
else
b
end
8. 繰り返し(イテレーター)
while i<10
puts i
i = i+1
end
until i>=10
puts i
i = i+1
end
10.times do
puts "hello"
end
10.times do |i|
puts "#{i}回目の繰り返し"
# ※0始まり
end
0.upto(9) do |i| # 9も含む
puts i
end
9.downto(0) do |i| # 0も含む
puts i
end
0.step(5, 2) do |i| #=> 0,2,4,6,8
puts i
end
object = 1..3
object = ["a", "b", "c"]
# 内部処理はeach文
for i in object do
puts i
end
object.each do |i|
puts i
end
loop do # 無限ループ
puts "hello"
end
break
:繰り返しを終了
next
:次の繰り返しに移動
redo
:もう1度同じ繰り返し
9. メソッド
- インスタンスメソッド
- オブジェクトをレシーバーとするメソッド
a.next
- クラスメソッド
- クラスをレシーバーとするメソッド
-
クラス名.メソッド
orクラス名::メソッド
File.open
File::open
- ドキュメントに書く際は
クラス名#メソッド
- 関数的メソッド
- レシーバーが省略されているメソッド
print
9.1 メソッド定義
- メソッド名を数字で始めてはいけない
-
return
を省略した場合- メソッドの中で最後の部分の値を返す
- 最後の部分が
puts
などの値を返さない場合はnil
を返す
- 実引数にハッシュを使うときは{}を省略できる
def f
puts "Hello"
end
def f(a)
puts a
end
def f(a,b,c)
puts a,b,c
end
array = [1,2,3]
f(*array)
def f(a=3)
puts a
end
# デフォルト値は右から指定する
def f(a, b, c=3)
puts [a,b,c]
end
# *を付けると配列として扱ってくれる。引数の個数を指定したくない時に便利
def f(*a)
pp a
end
f(1,2,3) #=> [1,2,3]
def f(a, *b)
puts a,b
end
def f(a, *b, c)
puts a,b,c
end
# キーワード付きで呼び出せる
def f(a:, b:)
puts a
end
f(a:1, b:2)
hash = {a:1, b:2}
f(hash)
def f(a: 1)
puts a
end
# ハッシュとして扱う。仮引数に定義していないキーワードを呼び出せる
def f(**a)
pp a
end
f(x: 1, y: 2) #=> {:x=>1, :y=>2}
alias new_f f # エイリアスを追加
alias :new_f :f
undef f # 定義しなかったことにできる
undef :f
9.2 ブロック付きメソッド
-
yield
で、与えたブロックをそのまま実行 -
yield
の引数の数とブロックの変数の数が違う場合は、足りない部分はnil
となる。多い部分は受け取らないだけ - ブロックの中で
break
を呼ぶと、ブロック付き呼び出しの場所まで一機に帰ってくるため、メソッドの返り値はnil
となる -
break 0
などとすることで返り値を指定できる
def f
yield
end
f do
puts "hello"
end
def f
if block_given?
yield(3)
end
end
f do |i|
puts i*i
end
def f(a)
if block_given?
yield(a,3)
end
end
f(2){ |i, j| puts i*j } # 2*3
f(2){ |i, j| puts i+j } # 2+3
array.each do |a|
puts a
end
hash.each do |i, h|
puts i
puts h
end
file = File.open("a.txt")
file.each_line do |line|
puts line
end
file.close
# 確実にファイルを閉じてくれる
File.open("a.txt") do |file|
file.each_line do |line|
puts line
end
end
array.sort { |a, b| a.length <=> b.length } # 昇順
array.sort_by{ |i| i.length }
# 多くのイテレーター(eachのように反復処理できるやつ)はブロックが与えられないときはEnumeratorオブジェクトを返すから、collectやmapなどを続けて呼び出せる
s.each_line.collect do |line|
line*2
end
s.each_byte.map do |byte|
byte & 1
end
s.each_char.map do |char|
char.next
end
10. ブロックをオブジェクトとして受け取る
a = Proc.new do |i|
puts i
end
a.call(3)
# 最後の仮引数に`&`を付けると、実引数は`Proc`オブジェクトに包まれて渡される(ブロック引数)
def f(a, &b)
puts a
puts b.call(3)
end
f(5) do |i| #=> 5,9
i**2
end
def g(&c)
f(5,&c)
end
g() do |i| #=> 5,9
i**2
end
array.each do |i; j|
# jはブロック内だけで有効な変数。ブロックの外側と同じ名前の変数をブロック内で使いたいときとかに。
end
11. 他のファイルを取り込む
-
require "a.rb"
: カレントディレクトリ(実行ディレクトリ)からの相対パス。Gemファイルなどを呼び出すのに使う -
requre_relative "a.rb"
: 実行ファイルからの相対パス。自分で作成したファイルなどを呼び出すのに使う -
.rb
は省略可能
12. 変数
- ローカル変数 :
_local
またはlocal
- グローバル変数 :
$glocal
- インスタンス変数 :
@instance
- クラス変数 :
@@classvariable
- 定数 :
Constant
- rubyにおいて、定数を変更することができる。警告が出るだけ
- また、定数が指すオブジェクトが変わっていなければ、オブジェクト自体に変更を加えても問題ない
MSG = 42
MSG += 5 #=> 警告
MSG = "a"
MSG.upcase! #=> 警告は出ない
13. 予約語
- 名前として使えない英単語
__LINE__ | __ENCODING__ | __FILE__ | BEGIN | END | alias | and |
begin | break | case | class | def | defined? | do |
else | elsif | end | ensure | false | for | if |
in | module | next | nil | not | or | redo |
rescue | retry | return | self | super | then | true |
undef | unless | until | when | while | yield |
|
14. 多重代入
a, b, c = 5, 6, 7
a, b, *c = 5, 6, 7, 8, 9
a, *b, c = 5, 6, 7, 8, 9
a, b = b, a
array = [1, 2]
a, b = array
a, = array
15. クラス
15.1 基本
- スーパークラス:継承元のクラス
- サブクラス:継承先のクラス
- Rubyの全てのクラスは
BasicObject
クラスのサブクラス - 通常のオブジェクトは
Object
クラスのサブクラス - インスタンス変数
- 同じインスタンス内なら値の参照、変更が可能
-
@
を付ける - 定義する必要は無い
- 初期化されていない場合
nil
を返す
- クラス変数
-
@@
を付ける - クラスの全てのインスタンスで共通
-
attr_accessor
などは使えない
-
- クラス内のメソッドでは、そのメソッドのレシーバーを
self
で呼び出せる - クラス内のメソッド内でメソッドを呼ぶ際には、レシーバーは暗黙に
self
となる - アクセス制限
-
initialize
メソッドは常にpublic
-
public
- インスタンスメソッドとして使えるように公開
-
private
- レシーバーを省略した形でしか呼び出せなくする
- 事実上インスタンスの外側から利用することができなくなる
-
protected
- 同一のクラス、サブクラスなら、インスタンスメソッドとして使える
-
- 既存のクラスにメソッドを追加することもできる
array = Array.new
array.class # Arrayと同じ
array.instance_of?(Array) # インスタンスか
array.is_a?(Object) # そのクラスまたはサブクラスのオブジェクトか
array.class.ancestors #スーパークラスとインクルードしているモジュール => [Array, Enumerable, Object, PP::ObjectMixin, Kernel, BasicObject]
array.class.superclass #=> Object
15.2 クラス定義
class A
Const = 3
@@ count = 0 # クラス変数
def initialize(x) # コンストラクタ
@x = x
end
private # これ以降がprivateになる
def set_y(y)
@y = y
end
public :set_y # メソッドをpublicにする
def z= (z)
@z = z
end
def output
puts @x,@y,@z
end
public :output
end
aa = A.new(1)
aa.set_y(2)
aa.z = 3
aa.output
A::Const
class B
attr_reader :x # ゲッターの定義
attr_writer :y # セッターの定義
attr_accessor :z # アクセッサーの定義
end
15.3 クラスメソッド
class << A
def f
puts "hello"
end
end
class A
class << self
def f
puts "hello"
end
end
end
class A
def self.f
puts "hello"
end
end
def A.f
puts "hello"
end
A.hello
A.instance_methods
# 特定のオブジェクトのみメソッドを定義できる(特異メソッド)
str = "hello"
class << str
def f
puts "hello"
end
end
str.hello
15.4 継承
- Rubyでは単純継承(単一継承)
- 複数のスーパークラスを持つことができない
class MyArray << Array
def [](i)
ii = i % size
# スーパークラスの同名メソッドを呼び出す
super(ii)
end
end
16 モジュール
16.1 基本
- Rubyでは名前空間と等しい
- 大文字で始める
module M
def f
puts "hello"
end
modulle_function :f
end
# モジュール関数
M.f
include M
f
16.2 Mix-in
- 仮想的なスーパークラスとして振る舞う
-
include
- インスタンスメソッドを追加
- moduleを後ろへ追加する
-
prepend
- インスタンスメソッドを追加
- moduleを前を追加する
- クラスのメソッドより前に呼ばれるので、メソッドを上書きできる
-
extend
- オブジェクト単位でモジュールをインクルード(特異メソッド)
- もう一つの機能としてクラスメソッドを追加できる
# A → M → Object
class A
include M
end
aa = A.new
aa.f
A.include?(M) # クラスAがモジュールMを含むか
# M → A → Object 既存のメソッドを変更できる
class A
prepend M
end
srt = "hello"
str.extend(M)
str.f
class A
extend M
end
17. 演算子
17.1 代入演算子
&&= | ||= | ^= | &= | |= | <<= | >>= |
+= | -= | *= | /= | %= | **= |
17.2 ビット演算
~ & | ^ >> <<
<<
: 左にずらす
17.3 論理演算子
- 左側から順番に評価
- 論理式の真偽が決定すると、残りの式は評価されない
- 最後に評価された式が論理式全体の値になる
s = s || "hello"
# 変数にデフォルト値を与える定番の書き方
s ||= "hello"
s = array && array.first
s = array&.first # ↑の短縮系
17.4 範囲演算子
- 内部的には
succ
メソッドを呼んでいる(与えられた文字列の次の文字列を呼び出すメソッド)
r = Range.new(1, 5)
1..5 #=> 1..5
1.. # 1から始まる、無限に長い数列
(1..).take(5) # 最初の5要素を抜き出す => [1, 2, 3, 4, 5]
1...6 # 1~5まで
"a".."b" # "a"~"b"まで
r.to_a
17.5 演算子定義
- 再定義できない演算子
:: && || .. ... ?: not = and or
class A
# 二項演算子
# 演算子をメソッド名として、メソッドを定義する
# 仮引数としてotherを用いることが多い
def +(other)
self.class.new( x + other.x, y + other.y)
end
# クラス名を入れてしまうと、継承したサブクラスでもAオブジェクトが返ってしまう
def -(other)
A.new(x - other.x, y - other.y)
end
# 単項演算子
# `@`を付け絵定義する
def +@
dup # オブジェクトの内容をコピーしたものを返す
end
# 添え字メソッド
def [](index) # a[2]とかに使う
end
def []=(index, val) # a[2] = 3とかに使う
end
end
18. 例外処理
18.1 基本
# 例外クラスを指定しないと、StandardErrorとそのクラスを補足する
begin
raise "Something went wrong!"
rescue => e
puts $! # 最後に発生したエラーのメッセージ => "Something went wrong!"
puts e.message # eのエラーメッセージ=> "Something went wrong!"
puts $@ # 最後に発生したエラーのバックトレース
puts e.backtrace # eのバックトレース
puts e.class # エラーのクラス => RuntimeError
retry
end
begin
# 処理
rescue Errno::ENOENT, Errno::EACCES
# 例外処理
end
val = "a"
x = Integer(val) rescue 0 # Integer(val)がエラーを出した時に0を返す => 0
def f
# 処理
rescue => e
#例外処理
end
begin
# 処理
rescue
# 例外処理
ensure
# 後処理
end
18.2 例外発生
raise "エラー"
raise StandardError
raise StandardError, "エラー"
# `rescue`節内では、最後に発生した例外をもう一度発生させる
# `rescue`節外では、`RuntimeError`を発生
raise
19. 代表的なエラーメッセージ
-
syntax error
: 文法ミス -
NameError
: 定義していないものが使われている -
ArgumentError
: 引数ミス -
TypeError
: メソッドの引数の型が違う -
LoadError
: ライブラリを読み込めない -
[BUG]
: Rubyや拡張ライブラリのエラー
20. Numeric
- Rubyはオーバーフローが無いらしい(いくらでも大きな値を扱える)
- 数値中の
_
は無視される123_456
-
Integer
とFloat
の掛け算はFloat
になる -
Math
モジュールに色々なメソッドがあるMath.sin(3.14)
Math.sqrt(2500)
- 変換 :
to_f to_i to_r to_c
123 or 0d123 | 10進法整数 |
0123 or 0o123 | 8進法整数 |
0x123 | 16進法整数 |
0b0101 | 2進法整数 |
12.3 or 1.23e2 | 浮動小数点数 |
12.3r | 有理数 |
123i | 虚数 |
# 有理数(分数)
a = Rational(1,3) #=> 1/3
a.numerator # 分子 => 1
a.denominator # 分母 => 3
# 複素数
b = Complex(1,3) #=> 1+3i
b.real #=> 1
b.imaginary #=>3
3**4 # 累乗 => 81
5.div(3) # 割り算 => 1
5.quo(3) # =>5/3
5.modulo(3) # 5%3
5.remainder(3) #=> 余り。符号は5に等しくなる
5.divmod(3) # => [1,2]
1.23.round # 少数第一位を四捨五入
1.23.round(1) # 少数第2位を四捨五入(少数第一位までにする)
1.23.ceil # 切り上げ => 2
1.23.floor # 切り捨て => 1
21. 乱数
# 0以上1未満のFloat型を返す
Random.rand
# 0以上3未満の整数型を返す
Random.rand(3)
# 0以上3未満のFloat型を返す
Random.rand(3.0)
# 種を与える
Random.new(1).rand # 毎回同じ値になる
22. 正規表現
22.1 基本
-
=~
で、何文字目で一致したかを返す -
大文字小文字の区別無し
"abcde" =~ /bc/i
-
-
は[]
の中の最初か最後になることで、単なる文字の-
として扱われる
r = /a/
r = Regexp.new("a")
r = Regexp.escape("a") # メタ文字をエスケープする
r = Regexp.quote("a") # escapeと同じ
r = Regexp.new("a", Regexp::IGNORECASE) # オプションを付ける
r = %r(a) # 下記4つは/がエスケープされる
r = %r<a>
r = %r|a|
r = %r{a}
"abc" =~ /a/
"abc" =~ /^a/ # 行頭 ※文字列の頭ではない
"abc" =~ /a$/ # 行末
"abc" =~ /[abc]/ # aまたはbまたはc
"abc" =~ /[A-Z]/ # A~Zのどれか
"abc" =~ /[a-z]/
"abc" =~ /[0-9]/
"abc" =~ /[A-Za-z]/
"abc" =~ /[A-Z0-9k]/ # A-Z0-9とk
"abc" =~ /[^a]/ # a以外
"abc" =~ /./ # 任意の1文字
"abc" =~ /\s/ # 空白、タブ、改行文字、改ページ文字 ※全角空白にはマッチしない
"abc" =~ /\d/ # 0-9
"abc" =~ /\w/ # A-Za-z0-9
"abc" =~ /\A/ # 文字列の先頭 \Aabcなど
"abc" =~ /\z/ # 文字列の末尾。末尾が改行文字の場合はその1つ前にマッチ abc\zなど
"abc" =~ /\z/ # 文字列の末尾 abc\zなど
"abc" =~ /\[/ # メタ文字を普通の文字として扱う
"abc" =~ /a*/ # 0回以上の繰り返し(一番長い部分にマッチ)
"abc" =~ /a*?/ # (一番短い部分にマッチ)
"abc" =~ /a+/ # 1回以上(一番長い部分にマッチ)
"abc" =~ /a+?/ # (一番短い部分にマッチ)
"abc" =~ /a?/ # 0または1個
"abc" =~ /a{3}/ # 3回の繰り返し
"abc" =~ /a{3, 5}/ # 3~5回の繰り返し
"abc" =~ /(abc)+/ # abcの繰り返し
"abc" =~ /abc|def/ # abcまたはdef
"abc" =~ /a/i # 大文字小文字の違いを無視
"abc" =~ /a/x # 正規表現内での空白、#以降を無視する。正規表現内にコメントを書きたいときなど
"abc" =~ /a/m # .が改行文字にもマッチ
"abc" =~ /a/mi # mとi
22.2 キャプチャ(後方参照)
-
$n
でn番目の()
内のマッチした文字列を取り出せる
"abc" = /(.)(.)(.)/
$1,$2,$3 #=> "a","b","c"
"abc" =~ /(.)(?:.)(.)/ # ?:をつけるとキャプチャ時に無視される
$1,$2 #=> "a","c"
"abc" =~ /b/
$` # マッチ部分より前 => "a"
$& # マッチした部分 => "b"
$' # マッチした部分より後ろ => "c"
22.3.1 破壊的メソッド
s.sub(/a/,"A") # 最初にマッチしたところを置き換える。ブロックを取ることもできる
s.sub(/b/) {|s| s.upcase } # /b/にマッチしたところを大文字に変える
s.gsub(/a/,"A") # マッチしたところ全てを置き換える
22.3.2 非破壊的メソッド
s.scan(/a/) # マッチする部分を配列の形で取得
s.scan(/(a)(b)/) # 二次元配列になる
s.scan(/a/) do |m|
puts m
end
s.scan(/(a)(b)/) do |a,b|
puts a,b
end
23. IOクラス
23.1 基本
- 標準入力:
$stdin
からデータを受け取る - 標準出力:
$stdout
へ出力 - 標準エラー出力:
$stderr
へ出力 - コマンドラインからの読み込み
- i個目のコマンドライン引数を
AGRV[i]
のようにして取得できる - 0始まり
- 型は文字列
- i個目のコマンドライン引数を
# 標準出力の出力先をtext.txtに変える
# 標準エラー出力の出力先はコンソールのまま
ruby a.rb > test.txt
$stdin.tty? # 標準入力がコンソールかどうか
23.2 メソッド
# ファイルからの読み込み
file = File.open("a.txt") # デフォルトでは"r"が指定される
file = Open("a.txt")
file = File.open("a.txt","r") # ファイルの先頭から読み込みのみ
file = File.open("a.txt","w") # 既存のファイルを0バイトに切り詰めるか新しくファイルを作成し、書き込みのみ
file = File.open("a.txt","a") # 存在しなければ新しくファイルを作成し、ファイル末尾に追記。書き込みのみ
file = File.open("a.txt","r+") # ファイルの先頭から読み書き可能
file = File.open("a.txt","w+") # 既存のファイルを0バイトに切り詰めるか新しくファイルを作成し、読み書き可能
file = File.open("a.txt","a+") # 存在しなければ新しくファイルを作成し、ファイル末尾に追記。読み書き可能
file.close # File.openにブロックを渡すことで自動的にcloseされる
file = File.open("a.txt")
s = file.read(5) # 5バイト分読み込む。引数省略時は全て読み込む
puts s
file.close
puts File.read("a.txt")
file.closed?
File.binread("a.txt") # バイナリーモード
File.write("a.txt","hello")
File.binwrite("a.txt", "010101")
file = File.open("a.txt")
file.each_line do |line|
p line
end
file.close
# 引数で区切られたものずつ読み込む(引数省略では"\n")
file.each("\n") do |line|
p line
end
while line = file.gets("\n")
puts line
end
file.each_char do |c| # 1文字ずつ
puts c
end
while c = file.getc
puts c
end
file.ungetc("a") # "a"をfileに戻せる(ファイル自体が変更されるわけではない)
file.each_byte do |b| # 1バイトずつ
puts b
end
while b = file.getbyte
puts b
end
file.ungetbyte("01") # 1バイト分の文字列をfileに戻す
file.readlines("\n") # 各行を要素とする配列の取得
file.lineno # 何行読み込んだか。変更可能な変数だが、ファイルポインタが変更されるわけではない
# 出力
file.puts 3 # 自動的にto_sが呼び出される
file.putc("abc") # 最初の1文字だけが出力
file.putc(50) # 文字コード50の文字が出力
file.write("abc") # 出力したバイト数を返す
file << "a" << "b"
# ファイルポインタ
file.pos
file.pos = 0
file.seek(5, IO::SEEK_SET) # 5バイト目の直後の位置にファイルポインタを移動
file.seek(5, IO::SEEK_CUR) # 今の位置から5先に移動
file.seek(5, IO::SEEK_END) # ファイルの末尾から5の位置に移動
file.rewind # ファイルポインタの先頭に戻す
file.truncate(5) # ファイルの長さを5に切り詰める
file.truncate(file.pos) # 現在のファイルポインタ以降を削除
file.binmode # バイナリーモードに変更
file.popen("コマンド") # fileから入力されたデータを使ってコマンドを実行する。コマンド実行時に得られる出力を返す
require "open-uri" # urlを普通のファイルのように開ける
require"stringio" # ファイルのような疑似的なオブジェクトを作れる
24. Fileクラス
File.rename("a.txt","b/c.txt") # a.txtをb/c.txtにする
File.delete("a.txt")
File.unlink("a.txt") # delete
require "fileutils" # ファイルのコピーや移動等
file.stat # ファイルの情報色々
File.ctime("a") # ファイル状態の最終変更時刻
File.mtime("a") # ファイルの最終変更時刻
File.atime("a") # ファイルの最終参照時刻
File.utime(Time.now, Time.now, "a") # atime,mtimeを変更
File.exsist?("a") # 存在するか
File.file?("a") # ファイルか
File.directory?("a") # ディレクトリか
File.readable?("a")
File.writable?("a")
File.size("a")
File.size?("a") # aのサイズが0より大きいか
File.zero?("a") # サイズが0か
File.basename("a/b/c") # ファイル名であるcを返す
File.dirname("a/b/c") # a/bを返す
File.extname("a/b/c") # 拡張子を返す
File.split("a/b/c") # ["a/b","c"]
File.join("a/b", "c") # "a/b/c"
File.expand_path("a","b") # ディレクトリb内での相対パスaを、絶対パスにする。bが省略されたときはカレントディレクトリを指定したときになる
__FILE__ # 現在のソースファイル名
require "find" # ファイルを検索できる
require "tempfile" # 一時ファイルの管理に便利
require "fileutils" # ファイルの移動や作成などが簡単にできる
25. Dirクラス
Dir.pwd
Dir.chdir("a") # cd
dir = Dir.open("a") # Fileクラスと同じメソッドが多い
while n = dir.read
puts n
end
dir.close
dir.each do |n|
puts n
end
dir.read
# globによって、ターミナルと同じように*や?などのパターンを使うことができる
Dir.glob("*") # カレントディレクトリの全てのファイル名を取得
Dir.glob(".*") # カレントディレクトリの、隠しファイルを含む布部手のファイル名を取得
Dir.mkdir("a")
Dir.rmdir("a")
__dir__ # 現在のソースファイルのディレクトリ名
26. 文字コード
- Rubyの文字列、正規表現は、文字列のデータと、文字コードをセットで保持している
- 正規表現は同じエンコーディングの文字列とのみマッチする
- コマンドラインで
ruby -E Shift_JIS test.rb
やirb -E Shift_JIS
などと書くことで出力用の文字コードを指定 - Fileクラスにおいて、
open
やread
などでもencoding
を指定できる
# encoding: Shift_JIS コメントでこれを書くことで、ソースコードの文字コードを指定できる
s.encoding
s.encode("utf-8")
# Encodeクラス
Encoding.compativle?(s1, s2) # s1とs2に互換性があるか(連結できるか) 連結した際の文字コードを返す
Encoding.find("shift_jis") # #<Encoding:Shift_JIS>
Encoding.list # 一覧を返す
Encoding.name_list
Encoding.find("shift_jis").name # "Shift_JIS"
### nkfライブラリ
# s.nkf(オプション文字列、変換する文字列)
# 文字コードのみを変換する場合は、-xm0を常に指定するのが良き
NKF.nkf("-S -x -xm0", s) # Shift_JISをUTF-8にする
NKF.nkf("-x -xm0", s) # 元の文字コードを自動で判別してくれる
27. 日時
27.1 基本
t = Time.new # 現在時刻
Time.now
Time.mktime(2024) # 2024-01-01 00:00:00
Time.at(300) # 1970/1/1から300秒
t.year
t.month
t.day
t.hour
t.min
t.sec
t.usec # 小数点(マイクロ秒)
t.nsec # 小数点(ナノ秒)
t.wday # 週の何日目か
t.yday # 年の何日目か
t.to_i # 1970年1月1日からの秒数
t.zone # タイムゾーン
t.utc_offset # 標準時との差(秒)
t.utc # タイムゾーンを世界標準時に変更
t.localtime # タイムゾーンをローカルタイムに変更
t1 < t2
t2 - t1 # 秒数が帰る
t.to_s
27.2 フォーマッティング
-
t.strftime("%y-%m-%d")
のような形でTime
をフォーマッティングできる
コード | 説明 | 例 |
---|---|---|
%A | 曜日 | Sunday |
%a | 曜日 | Sun |
%B | 月 | January |
%b | 月 | Jan |
%c | 日付、時刻 | Sun Jan 1 00:00:00 2024 |
%d | 日付 | 01 |
%H | 時刻(24時間) | 01 |
%I | 時刻(12時間) | 01 |
%j | その年の何日目か | 366 |
%M | 分 | 00 |
%m | 月 | 01 |
%p | 午前、午後 | AM |
%S | 秒 | 00 |
%U | その年の何周目か(日曜始まり) | 00 |
%W | その年の何周目か(月曜始まり) | 00 |
%w | 曜日(日曜日が0) | 0 |
%X | 時刻 | 00:00:00 |
%x | 日付 | 01/02/24 |
%Y | 西暦 | 2024 |
%Z | タイムゾーン | 東京 (標準時) |
%z | タイムゾーン | +0900 |
%% | %を出力できる | % |
※プラットフォームによって実行結果が異なる場合がある
27.3 timeライブラリ
require "time"
t.iso8601 # ISO 8601の形式にフォーマッティング
Time.parse("2024/01/01") # 文字列をTimeオブジェクトにできる。様々な文字列に対応している
Time.strptime("11/9/2018", "%m/%d/%Y) # parseでは対応していない文字列もTimeオブジェクトにできる
Time.strptime("令和6年1月1日", "令和%Y年%d月%d日") do |y|
y + 2018 # ブロックに年以外の情報を渡すことはできない
end
t.strptime("%Y/%m/%d") # 特定の形式で文字列を取り出す
27.4 dateライブラリ
require "date"
d = Date.today
d = Date.new(2024,1,1)
d = Date.new(2024,1,-1) # 2024/1/31
d.year
d.month
d.day
d.wday # 曜日(日曜日が0)
d.yday # 年の何日目か
d2 - d1 # 日数/1 と表示される
d + 1 # 1日先を取得
d += 1 # 1日先になる
d >> 2 # 2か月後の同じ日を取得
Date.new(2024,1,31) >> 1 # 2024/2/29
d.strftime("%Y/%m") # timeライブラリと同様に使えるが、時刻は全て0になる
Date.parse("R06.1.1")
t.to_date
d.to_time
28. Procクラス
- ブロックをオブジェクトにできるイメージ
pr = Proc.new do |s|
puts s
end
pr = Proc do |s| # newを付けなくても同じ
puts s
end
pr = proc do |s| # 小文字でも同じ
puts s
end
pr.call("hello")
pr["hello"]
pr.yield("hello")
pr.("hello")
pr === "hello" # この書き方だと、引数は1つだけ。case文などに使えるようにこの形式が定義されている
pr = Proc do |*a|
puts a
end
pr.call(1,2,3)
pr.call[1,2,3]
pr = Proc.new {|n| n%2 == 0}
(1..5).each do |i|
case i
when pr then puts i
end
end
# lambdaメソッドでProcオブジェクトを生成
# 引数の数のチェックが厳密になる
# ブロック内でreturnを使える
# lambdaメソッドでない場合のreturnは、Procオブジェクトを作成したメソッドから戻ろうとする
# breakも同様
pr = lambda do|a,b,c|
puts a,b,c
end
pr = -> (a,b,c) { puts a,b,c }
pr.call(1,2,3)
puts ["a","bc", "c", "defg","h"].sort_by { |a| a.length}
# :length.to_procオブジェクトが暗黙的に呼び出されることで、次のようにブロックを省略して書ける
puts ["a","bc", "c", "defg","h"].sort_by(&:length)
pr.arity # ブロック変数の数を返す ブロック変数が*aのように定義されているときは-1
pr.parameters # ブロック変数について、[種類, 変数名]の配列を返す
pr.lambda? # ラムダ式かどうか
pr.source_location # プロックが定義された位置[ファイル名, 行番号]
# クロージャー
# クラスのように手続きとデータの両方を保持できる
def counter
c = 0
Proc.new do
c += 1
end
end
c1 = counter
c1.call
c1.call
c2 = counter
c2.call
29. 組み込み変数
こちらの記事でまとめられている