たのしいRuby 第11章 Arrayクラス

Rubyイテレーターを理解するためにはArrayクラスをマスターするのが手っ取り早い。

今日はArrayクラスからのスタートです。今日もバリバリ書くぞぉ〜

っと、その前に・・・

いやなブログ - スクリプト言語用のデバッガの使い方 - Ruby, Python, Perlを見ながら、簡単なRubyPerlのデバッガの使い方を覚えた。

使い方は大体gdbと一緒。ポイントはrが無いこと。hでヘルプが見れる。

pデバッグの方が簡単かもしれないが、規模がでかくなってきたら活用したほうがいいと思う。

詳しい使い方はそれぞれ、プログラミングRuby言語蝙、ラクダ本に書いてある。

言語蝙を持っていないので、購入検討中〜。

も必見。

配列の作り方

連番の配列を作りたいときは、

irb(main):012:0> ("a".."d").to_a
=> ["a", "b", "c", "d"]
irb(main):013:0> (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Rangeクラスを使う手がある。

irb(main):017:0> Array.new(5, "foo")
=> ["foo", "foo", "foo", "foo", "foo"]

初期化も便利。

irbで漢字コード指定

pの時、文字コードが出てしまうとデバッグしにくいので、-Kuを付けて起動してみた。

% irb -Ku
irb(main):001:0> p %w{ゆうてい みやおう きむこう ほりいゆうじ とりやまあきら}
["ゆうてい", "みやおう", "きむこう", "ほりいゆうじ", "とりやまあきら"]
=> nil

irbでもいけた。化けてな〜い。

split

激しくよく使うのでしっかりやっておく。/etc/passwdの分解。

irb(main):016:0> open("/etc/passwd").each do |lines|
irb(main):017:1*  p lines.split(":")
irb(main):018:1> end
["root", "x", "0", "0", "root", "/root", "/bin/bash\n"]
["bin", "x", "1", "1", "bin", "/bin", "/sbin/nologin\n"]
["daemon", "x", "2", "2", "daemon", "/sbin", "/sbin/nologin\n"]

インデックスの使い方

Rubyの配列はすげぇ

irb(main):041:0> a = ("a".."d").to_a
=> ["a", "b", "c", "d"]
irb(main):042:0> a[1, 3]
=> ["b", "c", "d"]
irb(main):043:0> a[1..3]
=> ["b", "c", "d"]
irb(main):044:0> a[1, 0] = ["X", "Y"]
=> ["X", "Y"]
irb(main):045:0> p a
["a", "X", "Y", "b", "c", "d"]
=> nil

柔軟すぎる。

集合

集合も扱える

irb(main):054:0> a = ("a".."c").to_a
=> ["a", "b", "c"]
irb(main):055:0> b = ("b".."d").to_a
=> ["b", "c", "d"]
irb(main):056:0> a & b
=> ["b", "c"]
irb(main):057:0> a | b
=> ["a", "b", "c", "d"]
irb(main):058:0> a - b
=> ["a"]
irb(main):059:0> a + b
=> ["a", "b", "c", "b", "c", "d"]

ありえない。

Rubyは数学に強いらしい。

休憩〜

休憩中に、「るびま」の初回号を読む。

半分くらい話がわからん。もう一度読み返したい。

lispSmalltalkを学んだ方がいい。が・・・viper的にlispを使う機会が無い・・・来年あたりに・・・emacslispを学ぶかなぁ・・・。

GWはとことんRubyでいくぞぉぉぉぉぉ!!!!!!!!

破壊的メソッド

破壊的メソッドについてイマイチ理解できなかったけど、下のコードで理解できた。

irb(main):114:0> a = (1..10).to_a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):115:0> a.reject { |i| i > 2 }
=> [1, 2]
irb(main):116:0> a
=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
irb(main):117:0> a.reject! { |i| i > 2 }
=> [1, 2]
irb(main):118:0> a
=> [1, 2]
  • !が付いたら、aそのものを変更する。
  • !が付かなかったら,aを変更しない。

unshift,shift,pop,pushは!が付かなくても破壊的。

いろんなメソッド

配列系を全部試した。collect,zip,sort等かなり配列メソッドが充実している。使いこなせるのか疑問詞・・・。

練習問題

最後の問題が激ムズ!!

"括弧が正しく整列しているか判別せよ。"

しかも、"(", ")", "{", "}"混じりで。

ムズすぎなので、"(",")"のみにした。

p balanced?(%w"( ( ( ) ( ) ( ) ( ) ) )") # true
p balanced?(%w"( ( ) ) ( ) ( ) ( ) ) )") # false

悩んだ末、こんな感じになった。

#!/usr/bin/ruby

def balanced?(a)
  s = []
  a.each_with_index do |b, i|
    # p s
    case b
    when "("
      s.push(b)
    when ")"
      if s.last == "("
        s.pop
      else
        return false
      end
    else
      return false
    end
    if s.size == 0 && i != a.length - 1
      return false
    end
  end
  return true
end

p balanced?(%w"( ( ( ) ( ) ( ) ( ) ) )")
p balanced?(%w"( ( ) ) ( ) ( ) ( ) ) )")

セクシーじゃないけど、なんとかツリーを辿ることが出来た。特に最後がダメ杉。

これから答合わせしま〜す。

練習問題の修正

書き直した。やはり、答えの方が断然セクシー

#!/usr/bin/ruby

def balanced?(a)
  s = []
  a.each do |b|
    case b
    when "(","{"
      s.push(b)
    when ")"
      c = s.pop
      if c != "("
        return false
      end
    when "}"
      c = s.pop
      if c != "{"
        return false
      end
    else
      return false
    end
  end
  if s.empty?
    return true
  else
    return false
  end
end

p balanced?([])                   #=> true
p balanced?(["(",")"])            #=> true
p balanced?(["{","(",")","}"])    #=> true
p balanced?(["{","(",")"])        #=> false
p balanced?(["(",")","}"])        #=> false

p balanced?(["(", "{", "{", "}", "(", ")", "}", "(", ")", ")"]) #=> true
p balanced?(["(", "{", "{", "}", "(", "}", ")", ")"])           #=> false

最後の位置がマズかった。テスト項目も足りなすぎる。

popもすっきりしたし、eachでいけるようになった。

練習問題をやってみると、自分の基礎の足りなさに気づかされる。アルゴリズムも勉強しないとなぁ・・・。