Rubyの配列'Array'には"each_with_index"という便利なメソッドがある。
実際はArrayクラスに実装されているわけではなくArrayクラスがインクルードしている'Enumerable'モジュールで実装されている。

a.each_with_index do |item, index|
  puts "%s => %s" % [index, item]
end

と、こんな感じで使いブロックの中でindexを参照できるようになる。
Rubyの配列は他にもgrep、map、select等があるが、例えばこれらのブロックの中で"each_with_index"と同様にindexを参照するにはどうすればいいか?
単純に'map_with_index'なんて名前のメソッドがあればいいんだがどうやらそんなメソッドはなさそうだ。

Rubyのクラス'Object'にはこれまた便利な"methods"というメソッドがあるがこれはそのオブジェクトに定義されているメソッドを配列として返してくれる。
配列オブジェクトに対してmethodsを呼び出すと107個のメソッドを返してきたがこの中に"index"というメソッドがある。
このメソッドは引数にアイテムを指定するともしそのアイテムが存在したらそのアイテムの位置を返してくれる。

例えば

languages = %w/Perl Ruby Python PHP Java ActionScript Javascript C++ Scheme Smalltalk BASIC LISP/

こんな配列があり

languages.index('Python')

と呼び出すと数値の2を返してくれる。
これをmapメソッドの中で呼び出すことにより各要素のインデックスを参照できるようになる。
Rubyのヒアドキュメントは複雑な式を埋め込めるので

print <<EOT
<table>
<tr>
#{languages.map do |i|
languages.index(i) % 3 == 2 && i != languages.last ? "<td>#{i}</td>\n</tr><tr>\n" : "<td>#{i}</td>\n"
end}</tr>
</table>
EOT

こうしたら

<table>
<tr>
<td>Perl</td>
<td>Ruby</td>
<td>Python</td>
</tr><tr>
<td>PHP</td>
<td>Java</td>
<td>ActionScript</td>
</tr><tr>
<td>Javascript</td>
<td>C++</td>
<td>Scheme</td>
</tr><tr>
<td>Smalltalk</td>
<td>BASIC</td>
<td>LISP</td>
</tr>
</table>

のように出力される。
ただしindexメソッドは配列の内容が重複しているとうまく機能しない。
例えば

languages = %w/Perl Ruby Python Perl/

こんな配列だったとしたら

languages.index('Perl')

は常に0を返すからだ。

カテゴリ:

トラックバック(0)

トラックバックURL: http://blog.beanz-net.jp/beanz_mtos/mt-tb.cgi/39

コメントする