便利なメソッド

ここでは私が便利だと思ったメソッドを紹介します。

配列の便利なメソッド

map

mapは配列で最も使うメソッドのひとつです。 各々の要素に対してブロックを実行し、その値からなる新しい配列を返します。

print [1,2,3].map {|i| i+1} #=>[2, 3, 4]

#から改行まではRubyのコメントです。 コメントは実行の対象ではなく、プログラマーが説明やメモを書くためのものです。 Rubyの習慣として#=>は実行したときの画面出力を書いたり、式の値を書いたりします。 上のプログラムのコメントの意味は「プログラムを実行すると[2, 3, 4]が画面に現れる」ということです。 今までプログラムと実行結果を別々に書いていたのですが、この書き方でよりコンパクトに書くことができます。

  • 配列[1,2,3]にmapメソッドが実行される
  • mapメソッドは配列要素をひとつづつ取り出し、ブロックを実行する。 ブロックは波カッコで囲まれた部分(ブロックはdo〜endでも波カッコでも表せる)
  • 最初に配列から1が取り出されiに代入される。 ブロックで「i+1」が実行されると「1+1=2」となり、「2」がブロックの値になる
  • その値がmapメソッドの作る配列の最初の要素になる
  • 以下、配列の次の要素2を用いたブロックの値が3、3を用いたブロックの値が4なので、mapの返す配列は[2, 3, 4]となる。

ひとことでこのプログラムを表現すると「配列の各要素に1を加えた配列を求める」ということになります。 mapは配列オブジェクトを新たに作るので、元のオブジェクトは変更されません。

ディレクトリdir1/dir2以下のすべてのファイルのパス名の配列を作り、表示するには

d = "dir1/dir2"
paths = Dir.children(d).map {|file| d + "/" + file}
paths.each {|p| print "#{p}\n"}

mapメソッドもeachメソッドもブロックが短いので波カッコを使うのが良いと思います。 そうすることでプログラム全体の行数を抑えることができ、プログラムの全体を見渡すことができるようになります。

私は以前はdo〜endをブロックに用いることが多かったのですが、最近は波括弧が多くなってきました。 その使い分けはブロックが長いか短いかで決めています。

  • Dir.children(d)でディレクトリd直下のファイル名の配列が得られる
  • mapは各ファイル名に親ディレクトリをつけたパス名にし、その配列を返す
  • eachで各パスを順に取り出しprintメソッドで1行に1要素を画面出力する

mapでできることはeachでもできます。 最初の1を足す例をeachで書き直すと

b = []
[1,2,3].each {|i| b << i+1 }
print b, "\n" #=> [2, 3, 4]

eachを使う場合は空の配列bを用意して、そこに1を加えた要素を追加していくことになります。 mapより複雑なことをしていることがわかると思います。

一般に、配列は関連した要素(例えばあるディレクトリ直下のファイル全体)の集合を表します。 そのような集合の要素に対しては「共通の操作」を行うことが多いです。 mapはそのような共通の操作をまとめて行います。 ひとつひとつの要素に操作をするeachと比べ、まとめて行えるmapの方が優れているといえます。

inject

injectは「たたみこみ演算」を行います。 要素をひとつずつ取り出し、操作を行い、その結果を次の要素との演算に使います。 例えば配列[1,3,5]の要素を合計する操作を考えましょう。

  • 最初に1を取り出す
  • 次の要素3を加え(1+3=4)その結果4を次の操作に使う
  • 次の要素5を加え(4+5=9)その結果9が答えになる

この操作は同じ演算を繰り返し行っています。 これが「たたみこみ演算」です。

print [1,3,5].inject {|i, j| i+j}, "\n" #=> 9
  • 最初の要素1がiに代入される
  • 次の要素3がjに代入される
  • 1回目のブロックの計算(1+3=4)が行われる
  • 2回目の計算では前回の結果4がiに代入される
  • 次の要素5がjに代入される
  • ブロックの計算(4+5=9)が行われる
  • 9がinjectメソッドの値として返される

計算の初期値として引数を与えることもできます。 例えば、mapで[1,2,3]から[2,3,4]を作ったのと同じことをinjectで実現することができます。

print [1,2,3].inject([]) {|i, j| i << j+1}, "\n" #=>[2,3,4]
  • 最初に初期値として空の配列[ ]がiに代入される
  • 初期値がある場合は「次の要素」は最初の要素1になる。 1がjに代入される
  • 1回目のブロックの計算([ ] « 1+1)が行われる。 配列に(破壊的に)2が付け足され、[2]になり、その配列が返される
  • 2回目の計算では前回の結果[2]がiに代入される
  • 次の要素2がjに代入される
  • ブロックの計算([2] « 2+1)が行われる。 配列に(破壊的に)3が付け足され、[2,3]になり、その配列が返される
  • 3回目の計算では前回の結果[2,3]がiに代入される
  • 次の要素3がjに代入される
  • ブロックの計算([2,3] « 3+1)が行われる。 配列に(破壊的に)4が付け足され、[2,3,4]になり、その配列が返される
  • [2,3,4]がinjectメソッドの値として返される

これは、eachメソッドを使ったのと同じ方法です。 injectはeachに比べ、1行でコンパクトに書けるのが長所です。 私は以前はeachを使っていたのが、最近はinjectを使うようになりました。

sort

sortは配列をソートする(整列する)メソッドです。 たとえば

  • [1,3,2].sort =>[1,2,3]を返す(この配列は新規に作られたもので元の[1,3,2]はそのまま)
  • `[“bird”, “dog”, “cat”].sort =>[“bird”, “cat”, “dog”]を返す。文字列はアルファベット順(より正しくは文字コード順)になる

ソートをするためには、配列要素に<=>メソッドが定義されていることが必要です。 このメソッドはa <=> bに対し

  • a が b より大きいなら正の整数
  • a と b が等しいなら 0
  • a が b より小さいなら負の整数
  • a と b が比較できない場合は nil

を返します。 整数や文字列には<=>演算子があらかじめ定義されています。 なお、この演算子は「宇宙船演算子」といわれます。 その形がUFOに似ているからだといわれますが、その由来には諸説あるようです。 この演算子は様々なプログラム言語に実装されていて、比較(<=>)の元になる役割を果たしています。

sortは宇宙船演算子が定義されていないオブジェクトに対しては、ブロックで大小を評価することによってソートすることができます。 また、宇宙船演算子があっても、別の基準でソートしたいときはブロックを用います。 例えば、[1,3,2]を大きい順にソートするには、宇宙船演算子の符号を逆にするためにマイナスをかけます。 以下では小さい順と大きい順の両方を示します。

print [1,3,2].sort, "\n" #=>[1,2,3]
print [1,3,2].sort{|a,b| -(a<=>b)}, "\n" #=>[3,2,1]

数の文字列”9”、”5”、”13”、”20”、”12”、”4”を文字列としてソートするのと、数字としてソートするのでは結果が違います。

a = ["9", "5", "13", "20", "12", "4"]
print a.sort, "\n"
print a.sort{|a,b| a.to_i<=>b.to_i}, "\n"

to_iは文字列を整数に変換するメソッドです。 実行すると

["12", "13", "20", "4", "5", "9"]
["4", "5", "9", "12", "13", "20"]

となります。 文字列のソートは辞書順なので”12”が”4”よりも前にきます。

その他の配列でよく使うメソッド

uniqは重複を除くメソッドです。

[1,2,2,2,3].uniq #=>[1,2,3]

これは文字列の配列を扱っている時に使うことが多いです。

include?はあるオブジェクトが配列の要素になっているときにtrue、そうでないときにfalseを返します。

[1,3,5,7].include?(7) #=> true
[1,3,5,7].include?(8) #=> false

each系のメソッドは大変良く使います。 eachはすでに解説したので、このセクションでは省略します。

to_sメソッド

to_sメソッドはすべてのオブジェクトで実装されています。 そのオブジェクトを文字列に直すメソッドです。

1.to_s #=> "1"
1.23.to_s #=> "1.23"
[1,2].to_s #=> "[1, 2]"
1..2.to_s #=> "1..2"
{one: 1, two: 2}.to_s #=> {:one=>1, :two=>2}

このメソッドはprintメソッドの中で使われています。 printメソッドは、引数が文字列でなければto_sメソッドを使って文字列に直して表示します。 そのおかげで、任意のオブジェクトをprintが出力できるわけです。

ここでちょっとした注意。

print {one: 1, two: 2}

とするとエラーになります。 これはこのプログラムに曖昧さがあるためです。 メソッドの次には引数だけでなくブロック(実はブロックも引数なのですが)が来る可能性があります。 波括弧がブロックを表すとすると、ブロックの中が「one: 1, two: 2」で、これを無理やり実行しようとするとコロンのところでエラーになってしまいます。 このような曖昧さを避けるには丸括弧を使ってください。

print ({one: 1, two: 2})

printと丸括弧の間にスペースが無いほうが普通なのですが、あったとしてもこの文は実行できます。

to_sメソッドはダブルクォート文字列の式展開でも使われます。 式展開では、その式が文字列でなければto_sを使って文字列に直してから埋め込みます。 "abc = #{100}"では、100は整数なのでto_sが使われます。 このようにto_sは様々な場面で背後で活躍しているわけです。

to_sを直接使うことは少ないと思いますが、to_sのおかげでプログラム中の表現が簡潔になっていることが多いです。

<<メソッド

<<メソッドは文字列、配列、整数などで使われますが、オブジェクトによって意味が違うメソッドです。 また、このメソッドは二項演算子として使えますが、糖衣構文によってメソッドであると解釈されて実行されます。

"abc" << "de" #=> "abc".<<("de") => "abcde"
  • 文字列では、元の文字列に引数の文字列を破壊的に繋げ、その文字列を返す
  • 配列では、引数を配列に破壊的に付け加え、その配列を返す
  • 整数では、整数を二進数とみてそのビットを左に引数分だけずらす。 逆の演算子に>>があり、これは右にビットをずらす。 このとき小数点以下は切り捨てられる

余談ですが、機械語に近いレベルでは左シフトが2倍、右シフトが1/2倍を高速で行える演算としてよく用いられます。

chomp、chop、strip系メソッド

文字列のメソッドです。

  • chomp =>文字列末尾の改行を取り除いた新しい文字列オブジェクトを返す
  • chop =>文字列の最後の文字を取り除いた新しい文字列オブジェクトを返す
  • strip =>文字列の前後の空白文字を取り除いた新しい文字列オブジェクトを返す
  • lstrip =>文字列の先頭の空白文字を取り除いた新しい文字列オブジェクトを返す
  • rstrip =>文字列の末尾の空白文字を取り除いた新しい文字列オブジェクトを返す

lengthまたはsize

配列や文字列で使うメソッドで要素数、文字数を返します。

Time.now

現在の時刻のTimeオブジェクトを返します。

print Time.now, "\n" #=> 2022-09-19 16:10:15 +0900

年月日、時分秒が表示されます。 最後の「+900」はAsia/Tokyoの協定標準時(UTC)からの時差です。 したがって、UTCは「2022-09-19 7:10:15」になります。 UTCとの差が無いのはヨーロッパやアフリカのいくつかの国です。 アイスランドのレイキャビクの標準時はUTCに一致します。

2023

単項マイナスと構文解析

1 minute read

単項マイナスとは 単項マイナスと括弧 括弧なし単項マイナスを許容する場合のBNF calcの場合

Raccライブラリと構文解析

3 minute read

パーサ・ジェネレータとは 少し複雑な文法 四則(加減乗除)計算のBNF Racc で実装 クラス定義、BNFの記述部分 ヘッダー、インナー、フッター コンパイルと実行 演算子の優先順位と結合における左右の優先順位 まとめ

StrScanライブラリと字句解析

less than 1 minute read

StrScanライブラリのドキュメント 字句解析とは StrScanライブラリ StrScanライブラリを使った字句解析 実例

Gem

1 minute read

lbtというgemを作って公開してみた lbtはどんなgemか ファイルの配置 lbt.gemspec Rakefile gemのビルド RubyGems.orgへのアップロード 補足・・rake/gempackagetaskサブライブラリについて

Encoding

1 minute read

文字列のエンコーディングに頭を悩ませることはほとんどなくなりました。 なぜなら、どのアプリ、システムもUTF-8を使うようになったからです。 Rubyでもエンコーディングの問題が起こることはまず無いでしょう。 ですが、今回はエンコーディングの考え方を整理してみたいと思います。

Thread

less than 1 minute read

Fiberを書いたときから、次はスレッドを書こうと思っていましたが、時間がかかってしまいました。 その理由は、期待したとおりのスレッドの効果がなかったためです。 今回はそのことを書きますが、これはRubyのスレッドの抱えている問題なのか、自分のやり方が悪いのかははっきりしていません。

Fiber

1 minute read

Fiberは「ノンプリエンプティブな軽量スレッド」とRubyのマニュアルに記載されています。

RDoc

less than 1 minute read

今回はRubyプログラムから自動的にドキュメントを作成するRDocについて書きたいと思います。 私はこのことについて、エキスパートではありません。 この記事も、初心者の体験談だと考えてください。

Back to Top ↑

2022

Ruby/GTK4

5 minute read

Ruby/Gtkの記事を先日書いたときに、「これはかなり使える」という手応えを感じたので、WordBook(Railsで作った単語帳プログラム)のGTK 4版を作りました。 プログラムは「徒然なるままにRuby」のGitHubレポジトリに置いてあります。 レポジトリをダウンロードし、ディレクトリ_example/...

Shoes – Rubyとグラフィック

5 minute read

Rubyはグラフィックについて弱い印象があります。 しかし、グラフィックはデバイスに関することなので、言語そのものには直接の関係はないはずで、あるとすればライブラリです。 今後グラフィック関係のgemが開発されることに期待しましょう。

Rails7 テスト

5 minute read

前回作ったWordbook(リソースフル)のテストを書いてみます。 RailsのテストはminitestをRails用に拡張したものです。

Rails7 モデルとデータベース

2 minute read

今回はRailsにおけるデータの作成と保存、そして変更について説明します。 そのベースになるモデルとデータベースの話から始め、appendとchangeの動作について詳しく説明します。

Rails7とBootstrap

2 minute read

一般に、HTMLは文書の構造を表し、CSSはその体裁(見栄え)を表します。 Railsは最終的にCSSを含むHTML文書を出力するので、この2つについての理解が必須です。 この記事ではとくにCSSの人気ライブラリであるBootstrapを紹介します。 BootstrapはJavascriptも含んでいます。

Rails7のインストール

2 minute read

Rubyの最も人気のあるアプリケーションであるRuby on Railsを取り上げようと思い、書き始めました。 予想してはいましたが、相当な分量になってしまいました。 そのため、何回かに分けて記事にすることにします。 また、対象となる読者のレベルをどうしようかと考えましたが、「徒然Ruby」が基礎的な内容から始ま...

GemとBundler

1 minute read

Rubyのライブラリ管理システムのRubygemsとコマンドgemおよびbundlerについて説明します。

minitest(3)モックの詳細

2 minute read

minitestについて連続して2回書いてきました。 「minitestはドキュメントが少ない」という人がいますが、私も同感です。 例えば、モックとスタブの説明も少ないです。 そこで、今回はmock.rbのソースコードを参考に、モックの私的ドキュメントを書いてみました。 あくまで私個人の考えであり、minites...

minitest(1)テストとは

2 minute read

アプリ作成の記事でminitestを使いました。 今回はminitestについて、また一般にテストについて、私の考えを書こうと思います。

public、private、protected

2 minute read

今回はメソッドの呼び出し制限ついて説明します。 呼び出し制限にはpublic、private、protectedの3つがあります。

アプリ制作、インストール、テスト

1 minute read

2023/10/29 追記:この記事は新しく書き直しました。 古い記事で使っていたGitHubのCalcが大幅にアップデートされたためです。 そこで、この記事に合うようなプログラムsimple_calcを新たに作りました。 このプログラムは本レポジトリの_example/simple_calcにあります。

case文

2 minute read

if〜elsif〜・・・〜else〜endは皆さん良く使うでしょうか? これは場合分けで良く使われる方法です。 これと同様の制御構造にcase文があります。 Cのswitch文に似ていますが、より強力な機能を持っています。 if-else-endよりも高い能力があるといえます。

Lambda

1 minute read

Procオブジェクトを生成するメソッドlambdaについて説明します。

Proc オブジェクト

2 minute read

今回はブロックを一般化したオブジェクトProcを説明します。

モジュール

less than 1 minute read

モジュールには名前空間とミックスイン(Mix-in)の2つの機能があります。 ここではミックスインについて説明します。

Kernelモジュール

1 minute read

Kernelモジュールのメソッドはどこでも使うことができます。 そのメソッドの中には便利で有用なものが多いです。

便利なメソッド

1 minute read

ここでは私が便利だと思ったメソッドを紹介します。

文字列と正規表現

3 minute read

文字列は最も使うオブジェクトのひとつです。 特にウェブ・アプリケーションでは、コンテンツだけでなくHTMLのタグやCSSを含めすべてが文字列です。 Rubyは文字列オブジェクトのメソッドが充実しており、またパターンマッチのための正規表現も充実しています。

配列

2 minute read

配列は、どのプログラミング言語にもあると思います。 複数の要素を一括して扱うことができるのが配列です。 Rubyの配列はメソッドが充実しているので、プログラムを効率的、機能的に書くのに役立ちます。

トップレベルのメソッド

1 minute read

今回はメソッド定義です。 メソッド定義はRubyの核心ですが、今回はトップレベルに限って説明します。 この限定によって、内容はかなり易しくなっています。

ブロックとイテレータ

less than 1 minute read

ブロックはRubyの特長です。 ブロックのおかげで記述が非常にすっきりと分かりやすくなります。 今回はブロックをイテレータの本体として使う方法を説明します。

整数

less than 1 minute read

ここではRubyの最も基本的なオブジェクトである整数について説明します。

Hello world

less than 1 minute read

「徒然なるままに」をネットで調べてみると、「することもなく、手持無沙汰なのにまかせてという意味」とありました。 まさに、自分の現状を言い当てた言葉。 しかも、ブログに書くネタもなかなか思いつかない日々。

Back to Top ↑