Rubyのお勉強

トップページ

よーし、面白そうなRubyを勉強してみますか。

環境

  • Ruby1.9.2
    • これって、エンコーディングが変わったらしく、結構あちこちで問題が出てるらしいから、気をつけよう!

Rubyのお勉強メモ

全般

  • ファイルのエンコードは、先頭に記載?(例はWindowsでのSJIS、Ruby1.9.2のデフォルトはUTF-8)
    # encoding: sjis
    
    • うーん、微妙…。
  • 標準出力は、print,puts,pで、ちょっと違う
    • printは、改行なし
    • putsは、自動改行
    • pは、文字列をダブルクォートで囲んで表示?
  • 判定などの()は不要

構文

  • コメント
    # コメントはシャープ
    x = 10 # 行末まで全部コメント。/**/形式はない
    =begin
    ビギン-エンド形式の
    複数行コメントもあり
    この場合は、行頭に書く必要あり
    =end
    
  • 条件分岐
    • if-else-end
      if x == 10 then # thenは省略可能
        puts "x=10"
      elsif x == 20   # elseifじゃないのか…
        puts "x=20"
      else
         puts "x!=10"
      end
      
  • 配列(Array)
    • 基本はこんなん
      nums = [1,2,3,4,5]
      strs = ["a","b,"c"]
      
    • Array.newでもOK。この場合、初期値指定ができる
      a = Array.new
      a = Array.new(5)   # nilで5つ分初期化
      a = Array.new(5,0) # 0で5つ分初期化
      
    • シンプルに文字列を配列に入れるには、%wが便利
      abc = %w(abc edf) # 空白で区切って配列に入るよー。
      
    • splitでもOK
      abc = "abc 123 XYZ".split()
      
    • インデック指定だと、途中を飛ばしてもいいみたい。その場合は、途中はnilで初期化
      names = ["渡辺","田中","佐藤"]
      names[4] = "田辺"
      
  • イテレータ
    • each →これすごいな!
      • 基本はこんなで
        names.each do |name|
          puts name
        end
        
      • 他の短い記述で書いてみる
        names.each do |name| print name end # そのまま1行にしただけ
        names.each { |name| print name } # do,endを{}に変換→{}の場合は1行するのがルールみたい
        
    • whileで書き直す→途中でnilがあるから表示は止まるけど、そこまでは動く
      while name = names.shift do
        print name
      end
      
      • whileの時は、doも省略可能らしい
        names = ["渡辺","田中","佐藤"]
        names[4] = "田辺"
        while name = names.shift
          print name 
        end
        
    • timesメソッドを使うループは、直観的な書き方だなー
      5.times do
        print "hello!\n"
      end
      
  • メソッドはdefで
    def hello
      print "hello DEF\n"
    end
    hello()
    
  • ハッシュ
    • 基本はこんな感じ
      font_table = {:normal => '+0', :small => '-1', :big => '+1'}
      font_table.each do | key, val |
        print "key=[" + key.to_s + "],val=[" + val.to_s + "]\n"
      end
      
    • ハッシュの書き方は、2通り
      h = { 'key1' => 'val1', 'key2' => 'val2' }
      p h
      h = { key1: 'val1', key2: 'val2' } # こっちは1.9から。キーがシンボルになるよー
      p h
      
    • ハッシュからfetchで値をとると、キーが無い場合に例外が出る。デフォルト値を指定もできる
      puts h.fetch(:key3,"キーが無いよー")
      
    • ハッシュを作る時にデフォルト値を設定できる
      h = Hash.new('ハッシュのデフォルト値')
      puts h["no_key"]
      
    • しかも、デフォルト値をブロック処理可能
      h = Hash.new{|hash,key|
        hash[key] = key.upcase
      }
      puts h["no_key"]
      
  • 2次元配列の変わった初期化とか
    • 2次配列の一発初期化
      a = Array.new(5) {|i| i+1 }
      p a
      
    • これだと、同じオブジェクトで初期化されるから注意!
      a = Array.new(3, [0,0,0])
      a[0][1] = 2
      p a
      
    • 2つの配列で、同時に処理も可能。これ、使うかな…。
      ary1 = [1,2,3]
      ary2 = [10,20,30]
      ary3 = [100,200,300]
      result =[]
      ary1.zip(ary2, ary3) do |a,b,c|
        result << a+b+c # <<はpushと同じ
      end
      p result
      
  • 多重代入とか
    • 多重代入は、配列にも適用可能!
      ary = [1,2]
      a,b=ary
      p a
      p b
      
    • 配列から先頭だけ取りたい時は、a,
      a, = ary
      p a
      
    • 関数の引数で、不定引数にも使える
      def foo(arg,*args)
        p arg
        p args
      end
      foo(1)
      foo(1,2,3)
      
    • each_with_indexだと、|key,val|, indexをいっぺんに取れる
      hash = {:a => 100, :b => 200, :c => 300}
      hash.each_with_index { |(key,val),index | p [key,val,index] }
      
  • 文字列系
    • 文字列の長さは、length/size
      p "This is Ruby".length
      p "This is Ruby".size
      
    • 日本語だと、おかしくなるから、正規表現を使うらしいけど、encodingを指定してると、関係なさそう
      p "12345".length
      p "12345".size
      # p "12345".split(//u).length # UTF-8の場合→Ruby1.9の場合は、エラーになるよ!
      
    • 文字列をつなげるには+
      str1 = "最初の言葉"
      str2 = "次の言葉"
      str = str1 + str2
      puts str1,str2,str
      
    • 元の文字に追加するのは、<<でね
      str1 << str2
      puts str1
      
  • クラス
    • 基本はこんな感じ
      class HelloWorld # クラス名は大文字スタート
        def initialize(myname="Ruby") #コンストラクタはinitialize
          @name = myname # @でインスタンス変数
        end
        def hello # インスタンスメソッド。デフォルトはpublic
          print "hello world ", @name , "\n"
        end
        def HelloWorld.hello2(name) #クラスメソッドはnewしなくても使える
          print "hello world2 ", @name , "\n"
        end
        def self.hello3(name) #クラスメソッドはselfでもOK
          print "hello world2 ", @name , "\n"
        end
        class << self # クラスメソッドはこんな風にクラス定義もできる(複数メソッドの時はいいかな)
          def hello3(name)
            print "Hello2! ", name , ".\n"
          end
        end
      end
      bob   = HelloWorld.new("Bob")
      ruby  = HelloWorld.new
      bob.hello
      ruby.hello
      # クラスメソッドはどっちでも呼べる
      HelloWorld.hello2('Name')
      HelloWorld::hello3('Name')
      
    • アクセスメソッドは簡単でいいな!
      class HelloWorld
        attr_accessor :name #これだけで、setter/getter作るのと同じってイカス!
        def greet
          print "I am ", self.name ,"\n" # 自分はselfでアクセス
        end
      end
      ruby  = HelloWorld.new
      ruby.name = "hoge"
      ruby.greet
      
    • クラスの上書き
      class RingArray < Array
        def [](i)
          idx = i % size # レシーバを省略するとselfが自動でつくから、これは[self.size]で割ることになる
          super(idx)
        end
      end
      eto = RingArray[ "子","丑","寅","卯","辰","巳","午","未","申","酉","戌","亥" ]
      puts eto[6]
      puts eto[11]
      puts eto[15]
      puts eto[-1] # これが亥になる
      
  • ブロック
    • Rubyの特徴的な、「メソッドに処理を渡す仕組み」かな?
    • 正直、これに関してはうまく説明できる気がしないので、一番判り易かったリンクのみ
    • 最近は、このブロック渡しにインスパイヤされて、いろんな言語で実装されてるみたいだねー
  • モジュール
    • モジュールは、クラスを横断するメソッドを定義して、クラスにincludeして使うらしい(これをMixinと呼ぶだね)
      module MyModule
        #メソッド定義
      end
      class MyClass1
        include MyModule
        # ここでMyMduleのメソッドが使える
      end
      
    • 継承っぽいけど、単一継承じゃないからいっぱいincludeできる。。。
      • でも、これってせっかく単一継承にしてるのにどうなんだろ?
    • Mixinすると、同名メソッドはオーバライドされる
      • 順番は、includeは後勝ちで、その後に親クラスみたい
      • includeじゃなくて、オブジェクトに対してextendを使うと、そのオブジェクトに対してだけMixinできる、のかな?
    • あー、クラスに関係なくオブジェクトに直接関連づいたメソッドを「特異メソッド」って言うんだ。

ファイル出力とか

  • シンプルに引数のファイルの内容を出力
    print "-------シンプル版--------------------------------------------\n"
    print File.read(ARGV[0])
    
  • getsを使って、1行ずつ出力
    print "-------gets版--------------------------------------------\n"
    file = open(ARGV[0])
    while text = file.gets
      print text
    end
    file.close
    

TIPS

  • 良く使う簡素な判定と代入
    var = nil
    name = var || "Ruby" # varがnillなら"Ruby"を代入 →これはイイね!
    p name
    
    • 上記の記述は、以下と全く一緒
      name = "Ruby"
      if var != nil
        name = var
      end
      p name
      
  • 配列参照の場合は&&で楽できそう
    item = ary && ary[0] #aryがnilじゃなければary[0]を代入→これもイイね!
    p item
    
  • 自己代入は、||でもOK
    var ||= 1 # var = var || 1 と同じ
    p var
    
  • ブロックだと、自動で後処理を実行してくれる
    File.open("sample.txt") do |f|
      f.each_line do |line|
        puts line
      end
      # ブロックの後処理として、closeが自動的に行われるらしい
    end
    
  • ソート順を指定するのも、ブロック
    sorted = ary.sort do |a,b|
      a <=> b
    end
    p sorted
    
    • この「<=>」って面白いメソッドだなー
      • 左右のオブジェクトを比較して、「<」ならマイナス、「=」なら0、「>」ならプラスになるらしい!
  • sort_byなら、項目ごとの値の評価を1回だけ実行して、その値を元にソートする
    ary = %w( 1000 200 30 4)
    sorted = ary.sort_by do |item|
      item.length
    end
    p sorted
    

-
最終更新:2013年12月14日 11:05