全部で5部構成です。
- 目次
- 第1部「本を読もう」
- 第2部「知っておいたほうがいいこと」(Rubyの基礎?)
- Rubyからシステムのどこに行けて、何ができるか?
- 予備知識
- RubyGems
- 基礎文法
- メソッドを覚える重要性
- オブジェクトの基礎
- 基本キーワード(随時追加?)
- ハッシュと配列のメソッド名の互換性は高いです。
- to_ほにゃらら
- 改行コードを統一するイディオム
- CSVの扱い
- 順序・組み合わせ・直積
- Rangeオブジェクト
- 破壊的メソッド「!」
- ライブラリ「pp」
- よく使われる変数名たち
- 必要なメソッドとは(For初心者)
- 「畳み込み処理」とは?
- スキルの習得について
- ArrayとHashのアクセスの基本
- 多次元配列について
- 要素数を数える
- 文字列の配列化
- 数値
- 時刻・日時
- ファイル入出力(これもおおきなテーマ)
- ライブラリ「Fileutils」
- ディレクトリ・フォルダ
- Webサーバー
- ネットワーク
- タイマーメソッド
- 「Ruby逆引き本」に書いてあった誰かの言葉
- ブラウザ自動化「Selenium」
- 正規表現基礎勉強する。
- Regexp正規表現≠String文字列
- イディオム追加「Array.map(&:method)」
- まとめ(随時追加)
- 第3部「厳選メソッド60個」
- 【メソッド目次 – 60個】
- 第4部「候補から漏れたメソッド(随時追加)」
- 第5部「気づいたこと(随時追加)」
目次
第1部「本を読もう」
まず概要把握のため、簡単な入門本を読もう!以上。
第2部「知っておいたほうがいいこと」(Rubyの基礎?)
Rubyからシステムのどこに行けて、何ができるか?
- テキストファイルの読込、作成、追記(CSVも含む)「File.open、CSV」
- Web情報取得、ブラウザ操作「open-uri、Nokogiri、Mechanize、Selenium」
- ファイル、ディレクトリ操作「DirとFileutils」
- Webアプリ作成「Rails」
- 随時追加予定…
- …
- …
- …
有名どころのプログラミング言語はシェル言語と捉えてもいい気がする。
例えば「Ruby=シェル、Python=シェル」とか。
OSに命令を出して、たいていのことができるからシェル級だと思う。できないことのほうが少ないのでは?
予備知識
- クラスメソッドTime::now
- インスタンスメソッドString#slice
- ライブラリ利用require “ライブラリ名”
- 「Rubyはすべてがオブジェト」
- 変数は箱じゃなく名札
- Rubyリファレンスを見よう!
RubyGems
gemコマンドで他人のアプリケーションを利用して自分のやりたいことを達成する。
例
gem install rails
gem ○○○ ○○○
基礎文法
【リテラル】
リテラルとはRubyスクリプトに直接記述できる値のこと。
例えば、
「"abc", 123, 0.1, /abc/, ["a"], {a: "b"}, 1..10, :a」
などのこと。%記法は飛ばします。
【演算子】
使う、または使ったことがあるものをひとつずつ覚えていきましょう。そして自分だけの鉄板を持てればプログラミングが楽しくなると思います。ゆっくりひとつずつ覚えていきましょう。わからなかったら調べましょう。
※計算順序のコツ→数学みたくカッコ()をうまく使って順番を制御してみる。
「!, **, *, /, %, +, -, >, <, <=, >=, ==, !=, =~, or, and, ||, &&」など。
【論理式】
ベン図をイメージしよう!論理和、論理積、否定、真true、偽falseなど。条件式をたくさん作って感覚つかむ。
【自己代入】
+=, -=, /=
【コメント】
#コメント1行
=begin
コメント複数行
コメント複数行
コメント複数行
=end
【変数とスコープ】
文字列の始まりが小文字とアンダーバーならローカル変数。
ifとwhileの制御構造はスコープ無し。しかし、ブロックは注意。ネストやeachのブロック文のスコープに注意。
- @インスタンス変数→Rails以外で使ったことない。飛ばします。
- $グローバル変数→例:ブロック内での$a変数定義はスクリプト内のどこででも使用できる。
【条件分岐】
if 条件式
~
elsif 条件式
~
else
~
end
unlessは条件がfalseなら処理が実行される。ifの逆版と覚えておこう。しかしifの反転「!=」を使えればunlessは覚える必要がない気もする。初心者はこのくらいでいいか。
case文というものもあるが、あまり分岐したくないのが本音。現状多くの分岐を書くことはない気がする。if文に関してはよく使うので覚えると思います。後置ifは特徴的。簡単なifならこっちのほうが速く書けるかも?
【反復・ループ】
while
unitl
for~in
eachはあくまでもメソッドであり、制御構造とは言わないが「繰り返し」という意味では一番よく使う。
制御言葉→next, break, redo, catch~throw
ブロック付きループについて。
Rubyでは可読性がよくなります(そうらしい笑)。「each」とかのことです。回数、ループ状況が予想される、またはわかっているのであれば、ブロック付きループが有効です。
例えば3から8って決まっているなら、whileで3から8の条件式を作りよりも
(3..8).times { |i| 処理 }
のほうが速いし、わかりやすい。
【インクリメントとディクリメント】
Rubyにはありません。
【予備知識】
Railsやgemを使う前に…。
- 「オブジェクト.メソッド(引数1, 引数2)」について
↑これは普通の形。でもRailsとかは()がないときがある。
「オブジェクト.メソッド :引数1, :引数2」っていう。 - 「::」ってなに?
クラスメソッドの呼び出し方らしい。Nokogiriとかもそう。
格好つけてFile::open()ってしてる…(と思っている。)
【メソッド定義】
def abc(x, y, z)
処理
end
正直、自分だけわかればいいコードにメソッド定義使うことがいまのところない。メソッドやクラスの定義や細かい内容が出てくると、初心者にとっては辛くなる。だから俺は思い切って、飛ばします。大事なのはメソッドとレシーバーと制御文。あとやりたいことの流れをしっかりイメージすれば良し。何をどうこうしてどんな出力になればいいかを考えればいい。
【クラス・モジュール】
大事だけど(「だけど」じゃなくて、かなり大事)、小プログラムで定義するに及ばない。だからずっと成長しないのかな悲笑?俺はここのところ、いまは捨てます!
【例外処理】
begin
~
rescue
~
end
面倒だけど、これもかなり大事。特に他人にコードを使わせる場合大事。
でもいまは飛ばします。
メソッドを覚える重要性
メソッド覚えることは何がしたいか、何ができるかが明確になる。逆にメソッド名の文字列だけを覚える人ってのは少ないと思う。よって、メソッドを覚えることは自動的に用途、作用、意味を覚えることになる。ポーカーでもスリーカードとかフラッシュとかのポーカーハンドがある。この言葉だけ覚えてもしょうがない。名前のとカードの組み合わせを覚えるのは自然である。
メソッドを覚えることをかなりおすすめします。
「検索でよくない?」→はい、それも正解です。検索さえできれば物事が進んでいきます。適切な検索は神にでもなったような気分にさせてくれるでしょう。違いはスピードと効率化にあると思う。あとちょっとした高揚感。「俺、Rubyできてる笑?」という。ちょっとした勘違いともいえるが。
オブジェクトの基礎
【string化】
to_sとinspectの違いを調べる。
【同一と同値】
判定は「==」
オブジェクトIDの確認は「.object_id」
同一性の比較メソッド「.equal?」
【破壊的メソッド「!」】
「!」が付いていないものもある。
例:insert、[]=など。
【コピーしてからいじれば安心!?】
.cloneまたは.dup→.cloneが無難らしい。
b = a.clone
基本キーワード(随時追加?)
Rubyプログラミングを行う上で必要な知識や思い起こすためのトリガーワード。
演算子、配列、破壊、メソッド、制御構造・制御文(if、Whileなど)、CRUDの概念、文字列表現「”~”、’~’」、エスケープ、特殊文字、ヒアドキュメント、式展開#{}、「レシーバ、メソッド、パラメーター、リターンなど」プログラミングとはこの処理の繰り返し。
ハッシュと配列のメソッド名の互換性は高いです。
セクション3-3で60個にまとめたメソッドのハッシュメソッドの数が明らかに少ないのは、配列を先にまとめたため、自ずと配列とハッシュに共通しているメソッドをハッシュ側だけ省略することになったからです。
to_ほにゃらら
シンプルに使っていたけど、実は奥が深いみたい。でも俺はとりあえずシンプルに変換するときにだけ使おうと思う。深い部分はそのときはなんか問題かそれを使わないと達成できないことが起きたときに調べようと思う。
.to_s
.to_f
.to_i
.to_a
.to_h
.to_sym
改行コードを統一するイディオム
crlf = "newline\r\n"
p crlf.encode(crlf.encoding, universal_newline: true)
#=> 改行コードが「\n」に統一される?
使うとき調べてみましょう。あまり使わないかも。いや、統一して処理しやすくしたい時に使うかも。スクレイピングとかで改行文字を\n以外を使っていたとして、自分の土俵に持ってきたいときに、このメソッドを使うといいかも。メソッドの使い方自体は覚えなくてもいいから、「そういえば改行文字統一するやつあったな!」くらいでいいです。ちなみにgsubでもできます。要は改行コードを置換するだけです。ちなみにchompは、\r\nでも、\nでも、\rのどれでも削除対象です。置換と削除は違うけどね、復習として乗せておきます。
そもそも改行コードは「\r, \n, \r\n」の3つだけか?Railsで扱う時はどうすればいいんだろうか?
参考:https://qiita.com/uhooi/items/dc74ff3434aecb17faa2
crlf = "newline\r\n"
p crlf.gsub("\r\n", "\n")
p crlf.chomp
#"newline\n"
#"newline"
CSVの扱い
これは重要。なぜかって言うと、プログラミングは結局、何かしらを読み込んで(入力)、処理して何らかの形で成果物(出力)を作るか、処理自体が目的だからです。ファイルの入出力系はかなり重要です。
「require “csv”」これは覚えておくこと。プログラミング言語が処理するファイルってのはたいてい枯れた汎用ファイルである。テキストファイル(txt)、CSVファイル、HTMLファイル、JSONファイル、XMLファイルなどです。CSVはテーブルデータの利用にもってこいの形式(フォーマット)です。エクセルを使ってない会社というのは少ないと思うので、このデータ形式をプログラミングで扱えると強いと思います。ファイルの入出力には作る、書き込む、読み込む、、整形加工する、解析する(解析は今回なし。必要になったら調べる)などの機能があり、簡単ではありますが下記のテストデータを使い、VSCODEでtest.csvファイルを作成する。
test.csv
商品,価格
コーラ,120
オレンジジュース,130
ジンジャーエール,100
【読込】
参考:Google「csv ruby read readlines 違い」
https://qiita.com/mogulla3/items/2d2053f0e4c13ba3b6dc
https://uxmilk.jp/19202
https://docs.ruby-lang.org/ja/latest/class/CSV.html
Rubyで読み込み、CUIに表示する。返り値は「2次元配列」で返ってくる。全体を一度読み込んでしまうreadメソッドとブロックを使って1行ずつ読み込み処理するforeachメソッドがある。
CSV#readで全体を読み込む
require "csv"
csv = CSV.read("test.csv")
p csv
csv.each do |line|
p line
end
CSV#foreachで1行ずつ読み込む
require "csv"
csv = CSV.foreach("test.csv") do |line|
p line
end
個人的には前者の「csv = CSV.read(“test.csv”)」(シーエスブイドットリード)でOK。一度変数に入れて、一個ずつ処理したい。そういう性格。
そういえばヘッダーの扱いってどうなるんだろう。
ちなみに「require “csv”」を使わずにFile.read(“test.csv”)で読み込むと文字列で返ってきます。2次元配列ではなく文字列が返ってきます。
とにかく読込は、「File.read(“test.csv”)、CSV.read(“test.csv”)」でいきます。
【作成とデータ追加】
まずさっきのデータがあるのでデータ追加から。
「追加」≒「追記」として、末尾に追記するならaモードで開く。
追加や作成は「openメソッド」と「ブロック」を使います。
【追記】追記モードでオープン
CSV.open("test.csv", "a") do |csvfile|
csvfile << ["青森産アップルジュース", 200]
#csvfile.puts ["青森産アップルジュース", 200]
end
書いたら何事も無かったかのようにファイルが閉じられます。ほんの一瞬です。
※注意。元のCSVの最後の行が改行されてないと追記の1個目が最後の行の末に連結される。これ自動的に解消したいな。改行忘れありそうだし。元ファイルを手書きではなくRubyで作れば問題なさそうだな。コツ。プログラムでいじったら、プログラム以外でいじらないこと。プログラムで作成したものを手書きで(手動で)いじるとなんていうのかな、なにかしらファイルが汚染されるみたいな感じだ。
【作成】書き込みモードでオープン。値はすべて上書きされる。
require "csv"
array = [
["商品","価格"],
["コーラ",100],
["オレンジ",120],
["ジンジャーエール",130],
]
CSV.open("test.csv", "w") do |csvfile|
array.each do |ele|
csvfile << ele
#csvfile.puts ele
end
end
そうですね!「<<」か「puts」でRubyから作れば、自動的に一番下が改行されます。
このドキュメントではあえて調べないことが前提でしたが、CSVライブラリについてひとつだけ調べました。いつか、後日まとめてください。
参考:https://qiita.com/hkengo/items/1eefd2b8bd248f5f520d
参考:https://qiita.com/hkengo/items/59ba599ef48c613f2402
【ちなみにヘッダーについて】
参考:「Ruby csv headers」
https://shinkufencer.hateblo.jp/entry/2019/06/18/000000
https://qiita.com/shizuma/items/7719172eb5e8c29a7d6e
#読み込みに「headeers: true」を付ける。
csvfile = CSV.read("tttttt.csv", headers: true)
#「headeers: true」を付けるとcsvfileは2次元配列ではない。
#CSVオブジェクトらしい
p csvfile.class
p csvfile
#キーで値を取得できる
#さらにインデックスでも値を取得できる
csvfile.each do |row| #1行ごとに処理する
puts row["月"]
puts row[1]
end
果たして作成時に「:月」というシンボルで作っていたらアクセスもシンボルでいけるのか?
順序・組み合わせ・直積
- .permutation
- .combination
- .product
こんなのあるんだってことだけ覚えておいて!飛ばしまーす!
Rangeオブジェクト
Q.範囲指定(1..10)は配列[1,2,3,4,5,6,7,8,9,10]ですか?(「範囲オブジェクトは配列か?」)
A. 違います。範囲オブジェクトは「範囲オブジェクト」です。(1..10).classはRangeオブジェクトです。配列にするにはto_aをつけます。
#確認
p (1..10).to_a => Range
p (1..10).to_a.class => Array
puts ("abc" .. "hfr").to_a.sample
破壊的メソッド「!」
「!」がなくても破壊的なメソッドがある。気になるのであれば「p、puts」で確認する。あと「破壊」とか言ってるけど、OSの元データファイルまで壊すわけじゃないので全然怖くないし、何度でもやり直せる。
ライブラリ「pp」
require "pp"
user1 = [
{name: "太郎"},
{name: "花子"},
{name: "聡美"},
{name: "庄司"}
]
user2 = [
{name: "太郎", age: 20},
{name: "花子", age: 20},
{name: "聡美", age: 20},
{name: "庄司", age: 20}
]
pp user1
pp user2
値が2つないとppが発動しない!?なんだそれ笑!そういうものか…。
よく使われる変数名たち
変数名 | 意味 |
---|---|
k | キー |
v | バリュー |
i | 数字 |
x | 文字列、オブジェクト |
str | 文字列 |
array | 配列 |
hash | ハッシュ |
sym | シンボル |
ele | 要素 |
key | キー |
value | バリュー |
line | 文字列行 |
row | レコード行 |
必要なメソッドとは(For初心者)
覚えると得なメソッドがある。
またはいまの時点で「これ何に使うんだ?」というメソッドもある。例えば、selectメソッドがいい例だ。これは覚えたほうがいい。記述を短縮できて簡潔だからだ。こういうメソッドは積極的に覚えたほうがいい。使い方が少しだけ複雑なら、学習コストとストレスコスト、再現性コストとかいろいろな要素を天秤にかける。また、いま自分が知っているメソッドで応用を効かせて、やりたいことができないかを考える。
「畳み込み処理」とは?
複数配列の一括処理のこと?縦横計算?zipメソッドのこと?「畳み込み処理」っていう言葉があるらしい。
スキルの習得について
覚えると速いし、早い!しかもそれは直接、スキルと呼べる。特にプログラミングはパソコンだけあればいつでもどこでも何でもできるものである。いまのご時世とてもいいスキルだ。しかし記憶力というのは人それぞれで、少し時間が経つと忘れていくものだ。再度使う場合にまた同じ学習時間を要するには人生が勿体無さすぎる。覚えなくても基礎とアクセスする術を知っていれば基本的に問題はない。
「コトノハ」とはよく言ったもので、ある事に対して、派生、連鎖させて、「何を?」「どのくらい?」「どんなふうに?」話せるかが重要である。トリガーワードに対しての見方、側面、アプローチの方法や方向も人それぞれである。ツリー構造をイメージしたり、ノードとリンクから成るネットワーク図をイメージしたり、マジカルバナナのように言葉の連鎖をイメージしたりするなど、どんどんつながっていくと思う。またはそうなりたい。
どう調べて、何を調べて、何を言っているか、何が大事かがわかるようになればいい。簡単に言うとインテリジェンス。情報の扱い型がとても大事だ。情報の切り口、側面、過程、損得、利害関係、整理、入手方法、発信元の把握、信用、まとめ、整理、本質などそういう扱い方や捉え方。
記憶力はあればあるほどいい。検索システム等へのアクセスまたはその行為は記憶より遅く、セキュリティ上弱い。それは単に知識と一緒だ。「Xラーメン店」の位置を調べるより、知っていれば「早い」し、「速い」。
ArrayとHashのアクセスの基本
配列
array = [1, 2, 3, 4, 5, 6, 7]
p array[0] #インデックスは0から始まります
p array[2, 3]
p array[2..4]
p array.first
p array.last
array[0] = "z" #置換も可能。ちなみにこれが万能メソッド[]=""
p array[0]
ハッシュ
hash = { 名前: "太郎", 年齢: 34, 趣味: "釣り", 住所: "アメリカコロラド州", TEL: "12345678", }
{"x" => "y"} #記法1
{:x => "y"} #記法2
{x: "y"} #記法3
#ペアデータは「キーバリュー方式」
hash["x"]
hash[:x]
hash[x:] #値へのアクセスは後置シンボルが使えない。
hash[:x] = "m" #置換も可能。ちなみにこれが万能メソッド[]=""
多次元配列について
多次元とは言うても2次元が基本です。多くて3階層の入れ子までが私の限界です悲笑。
2次元配列はエクセルのようなテーブル表をイメージすることができます。外部サービスのAPIを利用して外部からデータをとってくると、入れ子がすごいときがあります。
table = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
p table
#アクセス
table[2][0] = 7
#ひとつずつ取り出すには二重ループ
table = [
[1, 2, 3],
[4, 5, 6],
[7, 8, 9],
]
table.each_with_index do |line, row_num| #row_numはインデックス値
line.each_with_index do |value, col_num|
puts "行#{row_num}、列#{col_num}、値は#{value}です。"
#エクセル風ならputs "行#{row_num + 1}、列#{col_num + 1}、値は#{value}です。"
puts "table[#{row_num}][#{col_num}] = #{value}"
end
end
もし上記のような使い方をするなら、丸暗記のほうが幸せになれると思います。「each_with_indexを2回使うんだな!」って。
または「ブロックパラメーターを複数取る」でもいいです。たぶん上記の「each_with_index」の2回使うより、ブロックパラメーターを複数取るほうが幸せになれると思います。
#「each_with_index」と複数ブロックパラメーターは同時に使えるか?
#使えました!これ結構用途広がる。
array = [["みかん", 120], ["すいか", 1200], ["ぶどう", 200],]
array.each_with_index do |name, price, index|
puts name
puts price
puts index
end
要素数を数える
「.count」 ≒ 「.length」→「必ずしも一緒ではない。」ということを知っておく。知りたかったら調べる。いまは遠慮しておきます。
Google検索「ruby count length size」とか。
文字数=> str.chars.count
行数=> strs.lines.count
文字列の配列化
「.linesメソッド」
Google「ruby lines String」
https://docs.ruby-lang.org/ja/latest/method/String/i/lines.html
文字列を改行文字で配列にする?…あれ?別のメソッドでなかった?splitのこと?
splitは改行文字で配列化するけど、半角空白文字でも区切るので、少し使い方が違う。
数値
integer.odd?
integer.even?
------------------------------------------------
乱数、ランダム
.rand
------------------------------------------------
array = (1..4).to_a
array.sum
------------------------------------------------
array.to_a.reverse
------------------------------------------------
(a..g)
------------------------------------------------
1.upto(3) { |i| }
(1..3).each { |i| }
3.downto(1) { |i| }
3.times { |i| }
------------------------------------------------
範囲オブジェクトは数字以外でも使えます。
now = Time.now
p (now..now+1)
------------------------------------------------
("air".."finaly").count
=>2765082個
Google「ruby date フォーマット」
https://techacademy.jp/magazine/18707
require "date"
date = Date.new
date.to_s→どうなる?
時刻・日時
Google「ruby date フォーマット」
https://techacademy.jp/magazine/18707
時刻計算
Time.now
日数計算
require "date"
puts Date.today
puts DateTime.now
…飛ばします。使う時に下記の用語・オブジェクトを検索して下さい。※時間系のオブジェクトの使い方もいずれは絶対必要になります!
- Time
- Date
- DateTime
- strftimeとparse
- 加減計算
- …
ファイル入出力(これもおおきなテーマ)
【基本】
open("ファイル名", "モード") do |f|
f.puts xxx
f.gets xxx
end
「f」はfileのf。
※Windowsのメモ帳で作成保存したものは「BOM」が付くので正しい情報が得られない可能性があります。「BOM」について不確定な知識ですがブログに書きました。Windows10(2020年)の最新からメモ帳にBOMなしが登場!?
【作成・書込・追記】
Google「ruby File open 省略」
https://uxmilk.jp/22615
参考書にはopenだけで書いていましたが、「File.open」ってのもあります。自分は慣れで「File.open」って書きます。あと「わかりやすさ性」も向上する気がします。
最初の新規作成はモードが”w”でも”a”でもどっちでもいいです。同じファイル名に”w”を使ってputsを行うと全部上書きされます。あとで調べたら”b”モードってのもあるらしい。b→バイナリー。
モード | 用途 |
---|---|
“a” | 追記 |
“w” | 書込 |
“r” | 読込 |
ブロックを使うと自動的に閉じてもくれるので、この書き方を鉄板にしましょう。逆にブロックを使わないやり方がわからない。ブロックのendが「閉じてます!」って感じするのでこれでいいと思います。
File.open("test.txt", "a") do |f|
f.puts "おはよう"
f.puts "こんにちは"
f.puts "こんばんは"
end
【読込】
「”r”読込モードで、f.readはStringを返し、f.readlinesはArrayを返す。」
↑ここ大事ね!というか基本。「レシーバー、メソッド、リターン」
でも、とりあえず「read」だけ覚えましょう。
#【read】
file = File.open("test.txt", "r") do |f|
f.read
end
puts file
puts file.class #String
#【readlines】
file = File.open("test.txt", "r") do |f|
f.readlines
end
puts file
puts file.class #Array
#【gets】
#getsだけだと1行しか読み込まない。
file = File.open("test.txt", "r") do |f|
f.gets
end
puts file
puts file.class
【読込短縮形】
「ファイルドットリード!!」または「ファイルドットリードラインズ!!」
開かなくていい!!(open()不要)
p File.read("test.txt")
#=>文字列 "おはよう\nこんにちは\nこんばんは\n"
p File.readlines("test.txt")
#=>配列["おはよう\n", "こんにちは\n", "こんばんは\n"]
ちなみに…。「instance method String#lines」について
https://docs.ruby-lang.org/ja/latest/method/String/i/lines.html
↑を参考に「readlines」の第二引数にchom: trueを付けたら、改行文字を消せました。
p File.readlines("test.txt", chomp: true)
#=>配列改行文字無し["おはよう", "こんにちは", "こんばんは"]
ライブラリ「Fileutils」
「require “fileutils”」使う時調べる!
ディレクトリ・フォルダ
これも調べる。「DirとPathname」(Pathnameはあまり使わないかも。)
Webサーバー
昔からあるWebrick。Rails5からPumaサーバー。また、調べたらフリーソフトで簡単なWebサーバー的なものがあります。目的は、ローカルで簡易システムを作成し、作業できればいいよね!って思いました。
ネットワーク
「require “open-uri”」Web上のhttpファイルを開けるように標準のopenメソッドを拡張します。
タイマーメソッド
#3秒待機
sleep(3)
「Ruby逆引き本」に書いてあった誰かの言葉
「プログラムが思った通りに動かない?いや、プログラムは書いたとおりに動いているだけだ。」
ブラウザ自動化「Selenium」
Selenium一択!
Seleniumを2日間集中し、あるプログラムを完成させて、数日手を加えないと何をやったかもう忘れている…。とてももったいない。
よって、わかりやすく、はいりやすく、より直感的に、受け入れやすく、情報をまとめる必要があります。この能力、社会に出てかなり大事かと。
正規表現基礎勉強する。
ミニ言語と言われている所以がだんだんわかってきた。
Regexp正規表現≠String文字列
正規表現を勉強するときに自然とこっちも学ぶと思う。
イディオム追加「Array.map(&:method)」
「アンドコロンメソッド名」
array = ["a", "b", "c", "d"]
array.map!(&:upcase)
p array
#["A", "B", "C", "D"]
puts ("abc" .. "hfr").to_a.map(&:upcase)
なぜこうなるか理解はしてません。procとかって言葉出た時点で拒絶反応出ます。とにかく複雑なことをしなけれ簡単に書けるということ。
「map &:text ruby」
https://qiita.com/k-penguin-sato/items/420d7487b28b5d58cac4
まとめ(随時追加)
- このドキュメントを繰り返し読む。もっと小さくできるなら努力する。簡易版を作ってもいい。
- 制御文を使えるようになる。鉄板文は忘れない。
- 演算子も少しずつ覚える。
- 「自分のカタチ」をつくること。
- 【追記】野村監督が亡くなった(2020年2月11日)。彼の言葉にはすべてに通ずる基本が詰まっているような気がする。その一つに「基礎が大事、みんなわかりきっていることだと思っているから、めんどくさがってやろうとしない。コツコツ、努力に勝る才能なし。」
- …
- …
第3部「厳選メソッド60個」
【厳選60個メソッドの概要】
勝手に厳選した60個のメソッドを「String専門のメソッド13個」と「それ以外の47個」に勝手に分類しました。さらに「それ以外の47個」は14個と33個に分かれます。また自分だけが覚えやすいようにゴロや形を作りました。もちろん今後、増減はあると思いますが、1年間はこの60個と増えるものは候補としてストックして見えるようにしておきたいと思います。
「String専門13個」
呪文:「サニサニエンコカタカナ、置換配列、文字大小」1,1,1,1,2,3,4
「それ以外47個」
呪文:「14個共通メソッド・確認メソッド系」2×4,3,1,1,1。コンビが4つ、サイレンカウ、class、encoding、match
呪文:「ユニーク1な晩メシ1を「mmsum3ガンダム2」にjoin1(積んで)して、『ジップとマージの4つの宝』6の位置6を地図1で確認して『配列CRUD』8(っていう名の装置)で探索する3」
【メソッド目次 – 60個】
- String専門(13個)
- それ以外(47個)
- 汎用系メソッド(14個)
- それ以外(33個)
60メソッド
strip
String.stripは文字列先尾両端の空白文字やメタ文字を削除する(半角文字のみ)。対象文字(空白、メタ文字)であっても、それが文字列中にあれば削除しない。文頭だけ削除したいのであればlstrip、文末だけならrstrip。lは左=文頭で、rは右=文末。とにかく目に見える文字列だけが欲しいなどサニタイズをするときによく使う。
chomp
String.chompは「末尾の改行文字」を削除する。chopと違い、末尾が改行文字では無いなら何もしない。
p "helllo\n" #=> "helllo\n"
p "helllo\n".chomp #=> "helllo"
encode
String.encodeは引数に文字コードを指定して、その指定した文字コードへの変換を試みる。変換先だけではなく、変換元も明記することができる。変換エラーが出ないようrepliceを覚えることおすすめする。スクレイピングなどで自分の環境と違うコードを取得する際に使用する。
str = "hello"
p str.encodeing #=> <Encoding:UTF-8>
p str.encode("cp932").encoding #=> <Encoding:Windows-31J>
p str.encode("cp932", "UTF-8").encoding #=> <Encoding:Windows-31J>
unicode_normalize(:nfkc)
String.unicode_normalize(:nfkc)は日本語の独特な癖を一括で処理する。人によって入力の違う全角半角カタカナと全角半角英数字。このメソッドは英数字はすべて半角に変換し、カナはすべて全角に変換する。変換系にはライブラリ「require “nkf”」というものもあります。「unicode_normalize(:nfkc)」でサクッと天下統一しちゃいましょう。
puts "MILKチョコは120円です".unicode_normalize(:nfkc) #=> "MILKチョコは120円です"
gsub
String.gsubは第一引数には検索する正規表現か文字列を指定し、第二引数には置換したい文字列を指定します。第一引数の検索値に当てはまるものを探し、第二引数の置換文字で当てはまるものすべて置換します。引数は正規表現と文字列が使えます。
#String".gsub("検索する文字列"または/検索する正規表現/, "置換したい文字")
puts "hello world".gsub("he", "ごはん") #=> "ごはんllo world"
puts "hello world".gsub(/wo/, "パン") #=> "hello パンrld"
sub
String.subは使用方法がgsubと同様で、subとgsubの違いは検索値で複数当てはまった場合、最初のひとつだけを置換します。
chars
String.charsは1文字ごとで区切った配列を返します。
p "str".chars #["s", "t", "r"]#=> ["s", "t", "r"]
lines
String.linesは改行文字で区切った配列を返します。
p "abc\nlm\nxyz\n".lines #=> ["abc\n", "lm\n", "xyz\n"]
split
String.splitは配列を返します。引数に指定した文字で分割し配列を作成します。引数に文字を指定しない場合は、半角空白文字で分割し、配列を作成する。注意したいのが「空白文字」≠「半角スペース」であり、指定なしだと\nや\tは分割文字として使用されます。引数には文字列または正規表現が使用できます。
str = "今日は,とて\tも いい天気 ですね"
p str.split #=> ["今日は,とて", "も いい天気", "ですね"]
p str.split(",") #=> ["今日は", "とて\tも いい天気 ですね"]
p str.split(/\s| /) #=> ["今日は,とて", "も", "いい天気", "ですね"]
p str.split(//) #=> ["今", "日", "は", ",", "と", "て", "\t", "も", " ", "い", "い", "天", "気", " ", "で", "す", "ね"]
upcase
String.upcaseはすべて大文字にする。
p "Hello".upcase #=> "HELLO"
downcase
String.downcaseはすべて小文字にする。
p "Hello".downcase #=> "hello"
capitalize
String.capitalizeは先頭を大文字にする。
p "hello".capitalize #=> "Hello"
swapcase
String.swapcaseはすべての文字列の大文字小文字を入れ替える。
p "heLLo".swapcase #=> "HEllO"
empty?
String.empty?はそのまま「Stringはカラですか?」と訳すことができ、レシーバーの値が空かどうかを判定し、結果をtrueかfalseで返します。
p "".empty? #=> true
p "hello".empty? #=> false
Array.empty?で配列データの有無を確認する。
p [1, 2, 3, 4, 5].empty?
nil?
String.nil?は「オブジェクト自体が存在してますか?」と問い合わせるメソッド。結果をtrueかfalseで返します。
str = nil
p str.nil? #=> true
p "hello".nil? #=> false
respond_to?
String.respond_to?(“メソッド名”)はレシーバーに対して引数のメソッド名が使えるかどうかをtrueかfalseで返します。検討のつくメソッド名が使えるかどうか確認するときに意外と使えます。
p String.respond_to?("class") #=> true
Array.respond_to?("メソッド")で引数に指定したメソッドが使えるかどうか確認する。
p [].respond_to?("count")
p "".respond_to?("count")
methods
String.methodsはレシーバーに対して実行できるメソッド一覧を表示します。あまり使わないです。
p "hello".methods #=> [たくさんある]
Array.methodsはレシーバーに対して使用できるメソッドの一覧を表示する。
p [].methods
#たくさん表示される
key?
Hash.key?(キー)は引数に指定したキーをデータ内に持つかどうか調べ、true・falseで返す。
hash = {one: 1, two: 2}
p hash.key?(:nine)
p hash.key?(:one)
false
true
value?
Hash.value?(バリュー)は引数に指定したバリューをデータ内に持つかどうか調べ、true・falseで返す。
hash = {one: 1, two: 2}
p hash.value?(9)
p hash.value?("coffee")
p hash.value?(2)
false
false
true
even?
数字.even?
偶数かどうかをtureかfalseで返します。
odd?
数字.odd?
奇数かどうかをtureかfalseで返します。「オッドアイ」のodd。
size
String.sizeは文字数を返します。
p "hello".size #=> 5
Array.sizeは配列に納められているデータ数を返す。
p [1, 2, 3, 4, 5].size
#5
length
String.lengthは文字数を返します。
p "hello".length #=> 5
Array.lengthは配列に納められているデータ数を返す。
p [1, 2, 3, 4, 5].length
#5
count
Array.countは配列数を返します。
p [1, 2, 3, 4].count #=> 4
Array.countは配列に納められているデータ数を返す。Stringにcountは使えない。
p [1, 2, 3, 4, 5].count
#5
class
String.classはStringやArray、Hashなどの所属クラス名、所属オブジェクト名を返します。デバッグによく使います。
p "hello".class #=> String
Array.classは所属するオブジェクト名を返す。Arrayに対して.classを実行すれば当然Arrayが返るが、Arrayかどうか不明の場合、役に立つメソッドだ。
p オブジェクト.class
encoding
String.encodingはShift_JISやEUC-JP、UTF-8などの文字コードを返します。
p "hello".encoding #=> <Encoding:UTF-8>
match
String.matchは引数に正規表現か文字列をとり、当てはまればMathDateオブジェクトをとり、当てはまらなければnilを返す。よくif文で使う。
p "hello".match(/l/) #=> <MatchData "l">
p "hello".match("l") #=> <MatchData "l">
uniq
Array.uniqは配列の中で重複しているデータがある場合、重複が削除され、1つだけ残る。
array = ["a", "g", "e", "a" ,"e", "f"]
p array #=> ["a", "g", "e", "a", "e", "f"]
p array.count #=> 6
p array.uniq #=> ["a", "g", "e", "f"]
p array.uniq.count #=> 4
[] = “”
万能メソッド[]=””
特に引数の理解と暗記が必要である。文字列を抜き出し機能もあれば、削除、書き換える機能もある。文字列Stringを配列として見立て、[インデックス番号]でアクセスする。引数の書き方は5つあり、他のメソッドでも応用できる書き方なので覚えたほうがいい。部分抜き出しや削除ではsliceとうメソッドもある。そして意外とArrayやHashにも使用できたりする。
- インデックス1文字ピンポイント指定
- 範囲指定
- 開始位置から何番目指定
- 正規表現
- 文字列指定
5つもあると言ったが、4つは意外と直感的である。少し頭の中で考えないといけないのが、3番目の「開始位置からいくつ」というものだ。
#str[~] = "~"
str = "BITTER_CARAMEL_LATTE"
p str
p str[2] + ", => インデックス2番目(実質3番目)"
p str[1..3] + ", => インデックス1~3番目"
p str[1, 2] + ", => 開始位置インデックス1番目自分自身を含めてそれ以降2つ"
p str[1, 1] + ", => これは自分自身だけを示す"
p str[/MEL/] + ", => 正規表現の表現方法"
p str["LAT"] + ", => 文字列指定"
x = str[5]
p x + ", => 別の変数xに1文字抽出保存できる"
「3.開始位置から何番目」について
他の4つと違い直感的ではないと思います。コツは第二引数が。「0と1とそれ以外」の3つの使い方を覚えればいい感じになると思います。
str = "BITTER_CARAMEL_LATTE"
puts "インデックス番号2の文字は「T」です。"
p str[2, 0] + ", => 自分自身との前の文字との間の空(くう)を示す?要するに自分自身の前を示す"
p str[2, 1] + ", => 自分自身を示す"
p str[2, 2] + ", => 自分を含めて自分以降2つを示す"
p str[2, 7] + ", => 自分を含めて自分以降7つを示す"
「0」は自分の前を。「1」は自分自身を。「それ以外」は自分を含めて後ろいくつか。
min
Array.minは配列の中の最小値を返す。
p ["a","b","c"].min #=> "a"
p [1, 2, 3].min #=> 1
max
Array.maxは配列の中の最大値を返す。
p ["a","b","c"].max #=> "c"
p [1, 2, 3].max #=> 3
minmax
Array.minmaxは配列の中の最小値、最大値を次のように配列にまとめて、配列で返す。[“最小値”, “最大値”]
p ["a","b","c"].minmax #=> ["a", "c"]
p [1, 2, 3].minmax #=> [1, 3]
sum
Array.sumは配列データがすうじに限り合計を返す。
array = [1, 2, 3, 4, 5, 6]
p array.sum #=> 21
shuffle
Array.shuffleは配列の並び順をシャッフルする。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.shuffle #=> 刻々と変わる
p array.shuffle #=> 刻々と変わる
p array.shuffle #=> 刻々と変わる
sample
Array.sampleは配列からデータを適当に抽出する。array.sampleとarray.sample(1)は返り値のクラスが変わります。引数に数字を入れて抽出する数を指定する。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.sample #=> "apple"
p array.sample(1) #=> ["greap"]
p array.sample(2) #=> ["banana", "orenge"]
join(ついでにinspectも)
Array.joinはinspectとは違い、値だけつなげて文字列化する。またArray.join(“,”)のように引数を指定すると、文字をつなげるときに文字と文字の間に区切り文字として使うことができます。ちなみにArray.join(“”)は引数なしと同じ意味です。
array = ["apple", "banana", "melon", "greap", "orenge"]
p array.join #=> "applebananamelongreaporenge"
p array.join("") #=> "applebananamelongreaporenge"
p array.join(";") #=> "apple;banana;melon;greap;orenge"
zip
Array.zipは転置配列を返します。転置配列?という言葉が聞き慣れませんが、戻り値を見ると考えうる利用方法の一つとして2つの配列の比較することに使用できます。一度使ったことがあります。zipはそれで返ってきた配列をeachで回すことで同時(比較)処理として扱うことができます。要素の数が合わなければ足りない部分はnilで埋められます。下記の例では「1と9を同時に取得してるので、同じ処理を2つにしたり、比較したりできる」ということです。
array_1 = [1, 2, 3, 4]
array_2 = [9, 8, 7, 6]
zip_array = array_1.zip(array_2)
p zip_array
#=> [[1, 9], [2, 8], [3, 7], [4, 6]]
new_zip_array = zip_array.select { |ele| ele[1] % ele[0] == 0 }
p new_zip_array
#=> [[1, 9], [2, 8]]
merge
Hash.mergeは2つのハッシュを合体し、かつ重複のないハッシュを返す。重複した時は追加ハッシュが優先され、元ハッシュは上書きされます。
hash_1 = {name: "taro", age: 24, hobby: "soccer"}
hash_2 = {tel: "00000000", hobby: "golf"}
p hash_1.merge(hash_2)
#=> {:name=>"taro", :age=>24, :hobby=>"golf", :tel=>"00000000"}
[] & | + – []
集合について。3つの集合と配列の足し算を1つ紹介する。
- 積集合[]&[]
積集合は「どっちにもあるもの」を集めた配列を返す。 - 和集合[]|[]
和集合は「どっちかにひとつだけでもあるもの」を集めた配列を返す。 - 差集合[]-[]
差集合は「引いたもの」の配列を返す。 - [] + []
「+」と「.concatメソッド」はどちらも結果は同じで、シンプルにつなげることができる。
p [1, 1, 2, 3, 4] & [1, 5 ] #=> [1]
p [1, 1, 2, 3, 4] | [1, 5 ] #=> [1, 2, 3, 4, 5]
p [1, 1, 2, 3, 4] - [1, 5 ] #=> [2, 3, 4]
array1 = [1,2,3,4]
array2 = [4,5,6,7]
p array1 + array2 #=> [1, 2, 3, 4, 4, 5, 6, 7]
p array1.concat(array2) #=> [1, 2, 3, 4, 4, 5, 6, 7]
map
Array.mapは式全体で配列を返します。例えば「array.map { |x| 処理 }」これ自体がmapで作成した配列を示し、保存しなければ戻り値を返した後に消え、別の変数を割り当てれば作成した配列を保存することができる。しかしmap!であれば元配列を新配列(破壊)に変えることができます。簡単の処理なら「do~end」より「{}」のほうがすっきりする。
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
p array.map {|x| x +1 }
#=> [2, 3, 4, 5, 6, 7, 8, 9, 10]
array.map! {|x| x + 1}
p array
#=> [2, 3, 4, 5, 6, 7, 8, 9, 10]
each
Array.eachは要素を1つずつ処理するように回す。よく使うので自然に覚えると思います。またネストされた2次元配列の場合、ブロックパラメーターに複数持たせると変数を複数利用できるようになる。これはかなり使い勝手がいいです。しかし、この辺は慣れが必要です。基本に従って声に出してゆっくり書いていけばうまくいくと思います。もし2次元配列でブロックパラメーターがひとつでも、配列アクセス[i]などで値を取り出すことができます。さらに三重ネストについて、下記のように()を使うことで一度のeachで三重くらいまで値を取り出すことができます。
array = ["a","b","c"]
array.each {|ele| p ele}
------------------------
nest = [
[1, "a"],
[2, "b"],
[3, "c"],
]
nest.each do |num, str|
puts "数字が#{num}で、文字が#{str}です"
end
------------------------
array = [[1, "a"], [2, "b"], [3, "c"]]
array.each do |ele|
puts ele[0].to_s + " and " + ele[1]
end
------------------------
nest_array = [[1, ["x", "y"]], [2, ["n", "m"]]]
nest_array.each do |l, (m, n)|
p "#{l}と#{m}と#{n}"
end
Hash.eachはデータペアごとに処理を回す。ブロックパラメーターの順番は守る。ブロックパラメーターは|key, value|で取っておけば問題ない。一方を使わなくてもこのように取っておけば問題が少ない。ちなみにブロックパラメーターを1つにすると配列で変数に格納する。直感的なのは|key, value|である。
hash = {one: 1, two: 2}
hash.each do |key, value|
puts "キーは#{key}で、バリューは#{value}です。"
end
hash = {one: 1, two: 2}
hash.each do |ele|
p ele
end
#[:one, 1]
#[:two, 2]
each_with_index
Array.each_with_indexはeachで回す際に値と同時にインデックス番号も取得することができる。ブロックパラメータを次のように複数指定する。|ele, i|の順番は決まっている。iはよく数字の変数で使われます。
array = ["apple", "melon", "banana", "greap", "orenge"]
array.each_with_index do |ele, i|
p "#{ele}と#{i}"
end
each_line
String.each_lineは複数行の文字列を配列化せずに1行ずつ処理を回すことができる。
"おはよう\nこんにちは\nこんばんは\n".each_line do |line|
p line * 3
end
each_char
String.each_charは文字列を配列化せずに1文字ずつ処理を回す。
"こんにちは".each_char do |char|
p char * 3
end
each_slice
Array.each_sliceはeachで回す際に何個ずつ取り出してブロックパラメーターに格納するかを決めれる。普通のeachは要素をひとつずつ取り出すが、下記の場合、一度に2要素を取得してそれらを配列にまとめて返す。
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
array.each_slice(2) do |ele|
p ele
end
.with_index
String.each_line.with_indexまたはString.each_char.with_indexは回す際にインデックスが必要な場合にこれを使う。ブロックパラメーターの2つ目がindexであること。「.with_index」メソッドはインデックス開始を任意の数字から始めることができる。
str = <<EOS
おはよう
こんにちは
こんばんは
EOS
str.each_line.with_index do |line, index|
p "行#{index + 1}:#{line}"
end
str.each_line.with_index(1) do |line, index|
p "行#{index}:#{line}"
end
push
Array.push(“値”)で配列の最後尾に”値”を追加する。Array.push(“値”, “値”, “値”)というようにコンマで区切ると複数のデータを最後尾に追加できる。「<<」にも「push」と同じ効果がある。
array = [1, 2, 3]
p array.push("hello")
p array.push("a", "b")
p array << "x" << "y"
pop
Array.popは配列の最後尾のデータを削除する。引数に数字を指定すると末尾から指定した数だけ削除する。array.pop(3)。pushとpopをペアで覚えるとよい。pushと違い、戻り値が違うかな?
array = [1, 2, 3, 4]
p array.pop #4
p array #[1, 2, 3]
array.pop(2)
p array #[1]
unshift
Array.unshiftは配列の先頭0番目にデータを追加する。コンマ区切りで複数データを追加できます。
array = [1, 2, 3]
p array.unshift("値")
#["値", 1, 2, 3]
shift
Array.shiftは配列の先頭データを削除する。引数に数字を指定すると先頭から指定した数だけ削除する。array.shift(3)。unshiftとshiftをペアで覚えるとよい。
array = [1, 2, 3, 4]
p array.shift
p array
#[2, 3, 4]
array = [1, 2, 3, 4]
p array.shift(2)
p array
#[3, 4]
insert
Array.insert(インデックス番号, “挿入データ”)で「インデックス番号の『前に』『挿入データ』を入れる」ということになる。万能メソッドを使いarray[2, 0] = “inject”でも同じ効果がある。array.insert(0, “inject”)とすればunshiftと同じ効果になり、array.insert(arr.length, “inject”)とすればpushと同じ効果になる。
array = [1, 2, 3, 4]
p array.insert(1, "insert")
#[1, "insert", 2, 3, 4]
String.insertも紹介しておく。動き、使い方はArrayと変わらない。指定したインデックス番号の文字の前に指定した文字を挿入します。第一引数にインデックス番号を指定し、第二引数に挿入したい文字列を指定する。
p "hello".insert(1, "zzz")
#"hzzzello"
slice
String.sliceは引数に指定した文字列または正規表現に当てはまったものを削除する。これはArrayにも使える。また戻り値を別の変数に保存すれば抽出として使用できる。部分削除したいならslice!で元データを破壊し、部分抽出をしたいならsliceといったところでしょうか。引数の指定方法は5つ。これは万能メソッドのところと共通するので、引数の5つの指定方法を覚えておこう。
str.slice(2) + " => インデックス番号2番目"
str.slice(0, 3) + " => インデックス番号0から3つ"
str.slice(3..5) + " => インデックス番号3からインデックス番号5まで"
str.slice(/CAR/) + " => 本来は正規表現の表現方法を使う"
str.slice("CAR") + " => 文字列指定"
delete
Array.delete(“データを指定”)として、引数には既知のデータを指定する。よって何が入っているか知っていないと使えない。配列に同じデータがあったら、すべて消える。
array = ["a", "b", "c", "d", "f", "g", "e", "a"]
p array.delete("a")
#"a"
p array
#["b", "c", "d", "f", "g", "e"]
delete_at
Array.delete_at(インデックス番号)は引数で指定したインデックス番号のデータを削除する。
array = ["a", "b", "c", "d", "f", "g", "e", "a"]
p array.delete_at(3)
#"d"
p array
#["a", "b", "c", "f", "g", "e", "a"]
scan
String.scanは配列を返します。String.scan(/正規表現/)またはString.scan(“文字列”)と記述し、レシーバー内を引数の正規表現または文字列で走査し、マッチした場合は引数に指定した正規表現または文字列のみの配列を返します。要するに複数マッチした場合は同じ要素がマッチした数、作成されます。
p "さんまのまんま".scan(/ま/)
#["ま", "ま", "ま"]
p "ヒット数は#{"さんまのまんま".scan(/ま/).count}です。"
grep
Array.grepは引数のパターンマッチを要素1つずつ判定し、当てはまったもの取り出し、それらで集めた配列を返します。動きがscanに近い。selectやrejectのようなブロックは不要である。grep(/正規表現/)、grep(オブジェクト)を入れる。grepによるパターンマッチは「===」で行われる。
「.grep」ひとつだけで、用途限定的ですが、mapやselect、scanのような動きをする。再度、連絡ですが、引数は正規表現かオブジェクトのみで文字列は取れません。以下は参考です。私みたいなエントリー者はシンプルな使い方を好む(私だけ!?)ので、おそらく1番最初の例のような「.grep(/文字列/)」になると思います。
array = ["only", "clearlly", "fast"]
p array.grep(/ly/)
p array.grep("e") #[]
p ["1", "2", "3", "4"].grep(/\d/)
p [1, 2, 3, 4].grep(/\d/)
p [1, 2, 3, 4].grep(/2/)
p [1, 2, 3, 4].grep(2)
p [1, "1,1", 3.14].grep(Numeric)
p [1, "1,1", 3.14].grep(Integer)
p [1, "1,1", 3.14].grep(String)
p [1, "1,1", 3.14].grep(Object)
p [0, 1, 1.1, 2, 3].grep(1..2)
select
Array.selectは配列から条件式に合ったものだけを集めた配列を返します。「Array.select { |x| 条件式 }」というこれ自体がselectで作成した配列示します(?)。保存しなければすぐに消えますが、select!として破壊的にすると元配列を新配列(破壊)に変えることができます。selectを使わない場合は、「新ハッシュとeachとifと<<」で同じことができます。
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
p array.select {|x| x.even?}
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
array.select! { |x| x.even? }
p array
Hash.selectの使い方は配列のselectと同様でなので直感的であると思われる。
hash = {name: "taro", age: 24, hobby: "soccer"}
sel_hash = hash.select do |key, value|
key.match("e")
end
p sel_hash
#{:name=>"taro", :age=>24}
第4部「候補から漏れたメソッド(随時追加)」
- sort
- reverse
- center
- rjust
- ljust
- 「+,<<」
- tr
- chop
- =~
- index
- match?
- clear
- inspect
- flatten
- first
- last
- each_index
- reject
- find
- partition
- take
- drop
- all?
- any?
- each_key
- each_value
- keys
- values
sort
Array.sortはデータの順番を自動的に昇順にする。降順にする場合は一度昇順に整えてから、反転させる。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.sort
p array.sort.reverse
#["apple", "banana", "greap", "melon", "orenge"]
#["orenge", "melon", "greap", "banana", "apple"]
reverse
String.reverseは文字列を後ろから読み、それを返す。
p "hello".reverse
#"olleh"
Array.reverseはデータの順番を逆にする。降順というわけではない。最初の並びをただ逆にするだけ。
array = ["apple", "banana", "melon", "greap", "orenge"]
p array.reverse
#["orenge", "greap", "melon", "banana", "apple"]
center
String.centerは文字列の幅を指定しておき中央寄せを行う。第二引数に指定がなければ空白部分をスペースで埋める。しかし第一引数の数字が文字数より小さいと何も起こらない。
p "hello".center(12)
#" hello "
p "hello".center(3)
#"hello"
p "hello".center(12, "☆")
#"☆☆☆hello☆☆☆☆"
rjust
String.rjustの使用方法はcenterと同様で、rは右という意味で右寄せになる。
ljust
String.ljustの使用方法はcenterと同様で、lは左という意味で左寄せになる。
squeeze
String.squeezeは「連続して重複する文字」と「連続して重複するスペース、改行文字」を1つにする。それは「まとめる」という言い方もできれば、削除という言い方もできる。引数にまとめる文字を指定することができる。
p "he\n\nll\t\tlo"
p "he\n\nl\t\tlo".squeeze
#"helo"
p "hello".squeeze(" ")
#"hello"
「+,<<」
String「+,<<」は文字列を連結する。「+」はシンプルに連結し、「<<」は元データを破壊して連結する。
String1 + String2 + String3
String1 << String2 << String3
tr
String.trはほとんど使わない。よって、しばらくして使わない場合は自分のメソッドリストから削除する。gsubにほぼ似ている?ただし引数は文字列だけか?置換、反転(それ以外)、削除、範囲指定などの指定方法があるようです。
str.tr("m", "A") #mをAに置換"
chop
String.chopは文字列の末尾の文字を削除します。とにかく最後の1文字を消す。改行文字とか関係ない。
p "hello"
p "hello".chop
#"hell"
=~
String =~ (/正規表現/)は文字列と正規表現を比較して、trueならマッチ開始位置を表示、falseならnilを返す。
str = "BITTER_CARAMEL_LATTE"
p str =~ (/TT/)
p str =~ (/Z/)
index
String.indexは引数に探索文字列を文字列か正規表現で指定し、当てはまった最初の開始位置を返す。第二引数に探索開始場所(インデックス番号)を指定できる。
str = "wjedfsdhelloehnrghnhellodhhfsnhello"
p str.index("hello")
p str.index("hello", 10)
p str.index("hello", 20)
match?
String.match?は引数に指定した文字列か正規表現の有無を確認し、trueかfalseで返す。match?の引数は正規表現、include?の引数は文字列。
str = "helloZZZ"
p str.match?(/ZZZ/)
p str.include?("ZZZ")
clear
Array.clearは空っぽ[]になるだけで、配列自体は無くならない。
array = ["a", "b", "c", "d", "f", "g", "e", "a"]
p array.clear
#[]
Hash.clearはデータを空にする。空っぽ{}にはなるがハッシュ自体はなくならない。
hash = { name: "taro", age: 18, hobby: "soccer" }
hash.clear
p hash
#{}
inspect
Array.inspectは文字通り記号も全部ほんとにそのまま文字列にする。to_sにも同じ効果がある。
array = [1, 2, 3, 4]
p array.inspect
#"[1, 2, 3, 4]"
flatten
Array.flattenはイメージとしてはネストされている配列のデータを一度全部取ってネストのない1次配列を返す。ネスト[]を取っ払って値だけで1次配列を返す。
ネストを平坦化する意味とは?引数なしだとすべて平坦化します。「すべて平坦化します。」っていう意味も何となく使っています悲。全ての値だけを取り出して、1次元配列にします。
引数には再帰数の階層を指定することができる。
nest = [[1, ["x", "y"]], [2, ["n", "m"]]]
p nest.flatten
#[1, "x", "y", 2, "n", "m"]
nest = [[1, ["x", "y"]], [2, ["n", "m"]]] #再帰数を指定する
p nest
p nest.flatten(0)
p nest.flatten
p nest.flatten(1)
p nest.flatten(2)
p nest.flatten(3)
first
Array.firstは配列の先頭データを返す。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.first
#"apple"
last
Array.lastは配列の最後のデータを返す。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.last
#"orenge"
each_index
Array.each_indexは配列の値はいらないけど、インデックス番号が欲しい時に使い、インデックス番号だけの配列を返す。しかし、インデックス番号があればarray[i]とアクセスが可能なのでこのメソッドの使い道がいまは不明である。
array = ["a", "b", "c"]
array.each_index do |i|
puts i
#puts array[i]
end
reject
Array.rejectの効果はselectメソッドの反対で、条件式に合わないものを集めて配列を返します。ifとunlessのような関係です。
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
reject = array.reject do |x|
x.even?
end
p reject
#[1, 3, 5, 7, 9]というように奇数だけ揃う
find
Array.findは配列から条件を満たす「最初の」要素を返す。
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
find = array.find do |x|
x.even?
end
p find
partition
Array.partitionはselectとrejectの処理を両方行い [[trueグループ], [falesグループ]]というネスト配列を返す。
array = [1, 2, 3, 4, 5, 6, 7, 8, 9]
a = array.partition do |x|
x.even?
end
p a
#[[2, 4, 6, 8], [1, 3, 5, 7, 9]]
take
Array.takeは引数に指定した数字をnとして、配列の先頭からn個だけの配列を返す。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.take(3)
#["apple", "melon", "banana"]
drop
Array.dropは引数に指定した数字をnとして、配列の先頭からn個削除した配列を返す。
array = ["apple", "melon", "banana", "greap", "orenge"]
p array.drop(2)
#["banana", "greap", "orenge"]
all?
Array.all?はブロックを利用し、配列のすべてのデータが条件式に合った場合trueを返す。
result = [1, 2, 3 , 4].all? do |i|
i >= 2 #条件式を書く
end
p result
--------------------
result = [1, 2, 3 , 4].all? do |i|
i >= 1 #条件式を書く
end
p result
any?
Array.any?はブロックを利用し、配列のデータのうち1つでもtrueがあればtrueを返す。
result = [1, 2, 3 ,4].any? do |i|
i >= 4 #条件式を書く
end
p result
each_key
Hash.each_keyはkeyだけを回す。
hash.each_key do |key|
puts key
end
each_value
Hash.each_valueはvalueだけを回す。
hash.each_value do |value|
puts value
end
keys
Hash.keysはキーだけの配列を作成し、返す。
hash = {name: "taro", age: 24, hobby: "soccer"}
p hash.keys
#[:name, :age, :hobby]
values
Hash.valuesはバリューだけの配列を作成し、返す。
hash = {name: "taro", age: 24, hobby: "soccer"}
p hash.values
#["taro", 24, "soccer"]
第5部「気づいたこと(随時追加)」
flattenとinpectが検索で使える
flattenとinpectの使い方がひとつわかった。
とにかく「ある文字」が引っ掛かるかどうかの検索のときに使えるのでは?
flattenすれば入れ子の階層も全部フラットになる。データ構造はバラバラになるけど、とにかくデータを探すときに役に立つかも。inspectはそれをStringにして、探索メソッドを使いやすくする。
スクレイピングとsqueeze
squeezeはスクレイピングしたときに謎のメタ文字や空白文字で文字が離れ離れになっているとき、見た目の簡素化するのに使える。
フリーソフト「clibor」との合わせ技reverse
reverseはクリップボードにコピーした順番を表示順に直すときに使える。