約 5,241,716 件
https://w.atwiki.jp/akcnv/pages/20.html
Rubyに関する小ネタ、気づき、メモなど。 NArray#to_f Ruby 1.9.x になって Array#to_s の挙動が変わった Ruby 1.9.x で Range#include? を使うときの落とし穴 cygwin への ruby 1.9 のインストール Cygwin への NArray, Ruby/GSL のインストールNArrayインストール Ruby/GSLをインストール NArray, NMatrix/NVector を相互変換したい 任意のオブジェクトをBool値へ変換する 配列の中身に重複があるかどうかを調べる Ruby どちらが速い? NArray#to_f to_fは倍精度実数ではなく単精度実数配列を返すので注意! 整数配列から倍精度実数配列に変換しようとすると、NArrayはスカラー値とのcoerceが効かないので narray + 0.0 等は使えない。どうすれば?? 方法1 NArray.float(*narray.shape) + narray 方法2 NArray.to_na(narray.to_f.to_a) 方法2は絶対値の大きな整数では精度が低下する恐れがある。 Ruby 1.9.x になって Array#to_s の挙動が変わった 1.9ではArray#to_sはArray#inspectの別名となった。 print等に配列をそのまま渡す場合等に問題が発生する。 Array#joinを使えば旧バージョンのArray#to_sと同様の結果が得られる。 Ruby 1.9.x で Range#include? を使うときの落とし穴 数字または文字列以外のRangeを使う場合は注意しなければいけない。 http //www.clear-code.com/blog/2010/3/25.html cygwin への ruby 1.9 のインストール 注:内容古し。今はrvmを使うのが吉。 最新版(ruby-1.9.1-p378.tar.bz2)をダウンロード、展開。 cd ruby-1.9.1-p378 ./configure --program-suffix=19 optflags="-O3 -march=native" make make install これで /usr/local/ の下にインストールされる。 この場合、ruby関連の実行ファイルの末尾には19が付く。 例えばruby本体はruby19、gemはgem19、irbはirb19として実行できるので、 ruby1.8との共存も問題なさそう。 最適化オプションが"-O2"だと parse.c のコンパイルでgccが固まってしまう場合があるので、"-O3"が無難。 makeの途中でなぜか segmentation fault が出てしまう場合がある。 その場合は、"-march=native" を削除するか "-march=i686" と書き換える。 Cygwin への NArray, Ruby/GSL のインストール 修正:2011年7月13日 gemでもインストールできるが、ソースの修正等が面倒。 そのため手作業で行ってみる。 http //diaspar-journal.blogspot.com/2009/01/rubygsl-narray-r.html を参考に、 NArrayインストール 最新版をダウンロード、展開し、そのディレクトリへ移動。 ruby extconf.rb make make install Ruby/GSLをインストール GSL と plotutils が cygwin にインストールされていることを確認。 Ruby/GSLの最新版をダウンロード、展開し、そのディレクトリへ移動。 rb-gsl-1.14.7では、そのままでは matrix_complex.c 1523 error conflicting types for ‘gsl_matrix_complex_equal’ /usr/include/gsl/gsl_matrix_complex_double.h 227 error previous declaration of ‘gsl_matrix_complex_equal’ was here vector_complex.c 1989 error conflicting types for ‘gsl_vector_complex_equal’ /usr/include/gsl/gsl_vector_complex_double.h 167 error previous declaration of ‘gsl_vector_complex_equal’ was here のように ext/matrix_complex.c と ext/vector_complex.c がコンパイルできない。 以下のように修正。 ext/matrix_complex.cの1523行目と1558行目の gsl_matrix_complex_equal を xgsl_matrix_complex_equal に修正。 ext/vector_complex.cの1989行目と2022行目の gsl_vector_complex_equal を xgsl_vector_complex_equal に修正。(教訓:GSLをC言語から使う場合、gsl_で始まる識別子を使わない。将来のバージョンで名前が衝突する可能性がある。) さらに、先にコンパイルしたnarrayのディレクトリからlibnarray.aを持ってきてextディレクトリ中にコピーする。 そして ruby setup.rb NArray, NMatrix/NVector を相互変換したい 例えば、あるNArrayオブジェクトに対してある部分では要素ごとの乗算を行いたいが、 別の部分では行列としての乗算を行いたい、など、NArray, NMatrix/NVectorを 相互に変換したくなる場合がよくある。 そんな時はreferメソッドを使おう。aがNArrayオブジェクトだとすると、 NMatrix.refer a で、aと同じデータを参照するNMatrixオブジェクトが作られる。 同様に、bがNMatrixオブジェクトだとすると、 NArray.refer b で、bと同じデータを参照するNArrayオブジェクトが作られる(NVectorも同様)。 配列データそのものは複製されないので、効率的に動作する。 ただし、複製ではなく参照なので、referで生成したオブジェクトを変更すると、 元の内容まで変更されてしまうので注意。 任意のオブジェクトをBool値へ変換する Rubyでは真偽値が必要なコンテキストでは、nilとfalseは偽、それ以外は真として扱われる。 では、あるオブジェクトhogeが真であればtrue、そうでなければfalseがどうしても欲しい場合にはどうすれば良いか。 hoge ? true false はダサすぎる。そんなときは… 方法その1: 演算子を使う(RubyリファレンスマニュアルのTrueClass参照。) true hoge 方法その2:二重否定 !!hoge 配列の中身に重複があるかどうかを調べる a.uniq == a とする。 irb(main) 001 0 a = [2,3,4,3,1,1] = [2, 3, 4, 3, 1, 1] irb(main) 002 0 a.uniq = [2, 3, 4, 1] irb(main) 003 0 a.uniq == a = false irb(main) 004 0 a = [2,3,4,1,0,5] = [2, 3, 4, 1, 0, 5] irb(main) 005 0 a.uniq = [2, 3, 4, 1, 0, 5] irb(main) 006 0 a.uniq == a = true 配列のサイズが大きい場合は a.uniq.size == a.size とした方が効率が良いだろう。 setを使う方法もある。 require "set" Set.new(a).size == a.size でもuniqの方が速いようだ。 Ruby どちらが速い? 別ページにしました。 Ruby どちらが速い?
https://w.atwiki.jp/startruby/pages/17.html
Rubyらしさ 文字列で遊ぼう! シンプルな文字列は を使う string = これは文字列です。 ん~~、普通! ちょっとフォーマットしたい時には""を使う バックスラッシュ記法でコントロール文字を埋め込みたい 変数の値を文字列にフォーマッティングしたい こんな用途に。 age = 18 string = "これは\n文字列です。\nボク永遠の#{age}歳!!" "#{}"の中は、かならず「式」として評価されるので、変数名がそのまま表記できる。 ちなみに、単なる計算式でもOK 主なバックスラッシュ記法 \t タブ \n 改行 \r キャリッジリターン \f 改ページ \b バックスペース \a ベル \e エスケープ \s 空白 \nnn 8 進数表記 \xnn 16 進数表記 \cx コントロール文字 (x は ASCII 文字) \C-x コントロール文字 (x は ASCII 文字) \x 文字 x そのもの 長文!ヒアドキュメント たとえば、HTMLのテンプレートな部分とか… たとえば、メールの長い典型文とか… そんな時はヒアドキュメント STRING = "EOS" これは 文字列です。 ボク永遠の#{age}歳!! EOS ちなみに、 EOS ~ EOS と書けば、 囲みの文字列と同等の扱いになり、 "EOS" ~ EOS と書けば、""囲みの文字列と同等の扱いになる。 ここから先の前提知識:ブロック ブロックとは? スコープの最小単位 do 実行文 end または { 実行文 } {~}の方がdo~endより少しだけ優先度が高い ブロック付きメソッド(いわゆるクロージャ) 使い方 def hoge(ary) ret = "result " ary.each do |i| ret += i end return ret end または def hoge(ary) ret = "result " ary.each { |i| ret += i } return ret end hogeメソッドからaryのeachを呼び出す eachメソッド内から、ブロックが呼ばれる|i|にeachからの引数(配列の内容)が渡る retに、渡された引数がどんどん連結される aryの内容をすべて連結した文字列を返す イテレータ 10回ループを普通にやると for i in [0..9] do p i end ブロック付きメソッドを使うと [0..9].each do |i| p i end …あんまり変わらないかな? でも、じつはこんなやり方も 10.times do |i| p i end for文より自然っぽくない? open/close制御 ファイルを開いて閉じるを普通にやると file = nil begin file = File.open("hoge.txt") 実行文 ensure file.close unless file == nil end ブロック付きメソッドを使うと File.open("hoge.txt") do |file| 実行文 end 何が便利かって、JavaやC#で起きがちな「クローズするためだけに延々とtry-finally記述が感染していく」がないこと! 例外ブロックも最適化できる! ブロック付きメソッドの作り方 def hoge 実行文 yield 実行文 end 引数があるときは def hoge 実行文 yield(item) 実行文 end 動性の高いRubyのリフレクション リフレクションという認識すらないくらい、「普通のこと」になっている。 これもまた、動的言語で「すべてがオブジェクト」の世界観が成せる技。 次のような動的拡張が可能になっている。 既存のクラスにメソッドを拡張する 既存のArrayクラスにhogeというメソッドを追加する場合、次のように書けば良い。 class Array def hoge end end これ、なんと組み込みクラスにも可能。 もちろん、既存のメソッドを書き換えることも可能! 既存のオブジェクトにメソッドを拡張する クラスにメソッドを拡張すると、なにかとメンドクサイ問題が出る場合がある。 そんな時は、対象となるオブジェクトにだけメソッドを拡張する。 array = [] def array.hoge end いちいち一個ずつメソッドを書き換えたり、メンドクサくない?って時にはMixIn モジュールとは「機能的に同じものをまとめて定義しておく」機能のこと。 クラスとは違い、継承ができないし、インスタンスの生成もできない。 「GUIでのコントローラをモジュールで表現」のような使い方をする。 「そのクラスの直接的な機能じゃないけれど、副次的に必要になるユーティリティ的機能」などをモジュール化しておくと、なにかと便利。 module KeyNameListItem def value @name = unless defined? @name @key = @name unless defined? @key if (@key == @name) return @name end return "#{@key} - #{@name}" end attr_reader key end というモジュールをつくっておいて、GUIで「このクラスをリスト表示したい!」というときにさらっと class Section include KeyNameListItem end というように、クラス再定義で組み込んでしまえる。 もちろん、オブジェクトにもMixIn section = Section.new section.extend KeyNameListItem これらの再定義をうまく使っていくと、JavaやC#にありがちなXxxUtilとか、XxxHelperとかいったクラスが必要ないという事に気づくはず! さあ!いま、Rubyという自由の羽を得た!! 飛び立とう!! めくるめくオブジェクトの世界へ!!
https://w.atwiki.jp/akcnv/pages/16.html
CygwinでTinkerをコンパイルする http //dasher.wustl.edu/tinker/downloads/ から、tinker最新版(現在 tinker-5.1.09.tar.gz)をダウンロードし、/tmpに置く。 /tmpに移動して、 tar zxvf tinker-5.1.07.tar.gz cd tinker cp mmff/*.[fi] source cp makefile/Makefile source cd source/ rm *.c Makefileの修正 注意点:precise.fは-ffast-mathオプションを付けてコンパイルしてはならない。 それを踏まえて、Cygwin/gfortran用に書き直したMakefileが下のファイル。 ktors.fの410行目でコンパイルエラーが出るので、次のように書き換える。 旧 if (skipring.eq..true.) then 新 if (skipring) then Makeして実行。segmentation faultが出る… fbounds-checkを付けてコンパイルし、実行してみると At line 168 of file cluster.f Fortran runtime error Array reference out of bounds for array kgrp , lower bound of dimension 1 exceeded (0 1) cluster.fの168行を修正することで対処する。 旧 call sort (size(i),kgrp(igrp(1,i))) 新 if (size(i) 1) then call sort (size(i),kgrp(igrp(1,i))) end if 実行。今度は、 At line 115 of file switch.f Fortran runtime error Substring out of bounds upper bound (6) of mode exceeds string length (3) サブルーチンswitchの引数を文字列ではなく整数に換えれば解決。 そのため、下の、trans_switch.rbをtinker/に置き、 ruby trans_switch.rb source/*.f とする。そして、source/switch.fで、modeの型をintegerに書き換える。あとは make make rename で終了。 追記 環境によってはSegmentation faultが出て落ちるようだ。最適化オプションを-O2にしたら動くようになった。原因不明。 最終更新日:2011-02-04
https://w.atwiki.jp/kmo2/
ここは、私がRubyのお勉強のために使うページ。 Rubyはとてもエレガントなスクリプト言語だと思うんだけど、どうにもよく分かってないんでここにメモをしていく。
https://w.atwiki.jp/shin-b/pages/24.html
rubyダウンロード OpenSSL-0.9.8e for windows (Win32 version) mingw http //sourceforge.net/projects/mingw/files/ libs http //jarp.does.notwork.org/win32/ rubygems http //rubyforge.org/frs/?group_id=126 $ tar xfz ruby-1.9.2-p0.tar.gz $ ls ruby-1.8.2-preview3.tar.gz ruby/ $ mv ruby ruby-1.8.2-preview3 $ cd ruby-1.8.2-preview3 $ ./configure make (略) $ ruby -v ruby 1.8.2 (2004-11-06) [i386-mingw32] ./configure --enable-shared --prefix=c /ruby/ruby-1.8.7-p302 ./configure --enable-shared --prefix=c /ruby1.9 make make test make install C /Develop/MinGW ./configure --prefix=/c/Develop/MinGW make make check make install これで /c/MinGW/lib に libz.a がインストールされるので、ひきつづき Ruby のソースディレクトリに戻り、 cd ext/zlib ruby extconf.rb --with-zlib-dir=/c/Develop/MinGW make make install $ cd ruby-1.8.5/ext/zlib $ ruby extconf.rb --with-zlib-include=/usr/include -with-zlib-lib=/usr/lib $ make $ su # make install export PATH=". /usr/local/bin /mingw/bin /bin /c/ruby/ruby-1.9.2-p0/bin" /c/ruby/ruby-1.8.6-p369-i386-mswin32/bin export PATH=". /usr/local/bin /mingw/bin /bin /c/ruby/ruby-1.9.2-p0/bin" Ruby 1.9.1 をビルド Windows, MinGW, Ruby ソース ruby-1.9.1-p129.tar.bz2 を落として展開したら、以下のコマンドを順に実行します。 ./configure --enable-shared --prefix=c /ruby1.9 make make test make install make test で、 「(809/934) tests failed」となりますが VC でも同じだしとりあえず無視。 それから、MSYS 上で gem や rake を使うために、ソースディレクトリの bin から gem, irb, rake, rdoc, ri を c /ruby1.9/bin にコピーします。 (prefix を MSYS と分けたのは、Ruby は MinGW のないところでも使うから) zlib のインストール 案外すんなり行くものですが、実はこれだけだと zlib.so がないため gem が動きません。 まずは zlib のソース zlib-1.2.3.tar.gz を取得して展開し、さっくりコンパイルします。 ./configure --prefix=/c/MinGW make make check make install これで /c/MinGW/lib に libz.a がインストールされるので、ひきつづき Ruby のソースディレクトリに戻り、 cd ext/zlib ruby extconf.rb --with-zlib-dir=/c/MinGW make make install gem コマンドを実行して、ヘルプが出ればOKです。(zlib.soがないとヘルプさえ出ない gem の仕様も問題だけど)
https://w.atwiki.jp/startruby/pages/28.html
Start! Ruby Start!! Ruby View more presentations from mitim. 目次 なぜRuby? Smalltalkの思想を模倣した設計思想 基本的な構文 Rubyらしさ Rubyでもドキュメンテーション これだけは覚えておきたい!コマンド たくさんあるよ!ライブラリ 外部リンク
https://w.atwiki.jp/startruby/pages/14.html
なぜRuby? 短期化する開発 3ヶ月単位の開発が増えてきた! 開発者は黙って徹夜休出を耐えるしかないのか? 開発現場を効率良く回す OSSフレームワークを効果的に採用する 自動化できる部分はできうる限り自動化する 自動化できる部分はできうる限り自動化する CI等大きなツールはOSSを利用 DBにリソースを放り込むとか細かい糊的ツールが必要 つくらにゃ! 自動化するためにはツールをつくらにゃ! ツールのキモは「素早く実装」「使いながらメンテ」 開発対象の言語で作る! c#にしてもJavaにしても重厚感はいなめない Excelのマクロ! nullとNothingの嵐に眩暈が WindowsScriptingHostを使う! OfficeはOLEで使えるけど、ライブラリ不足が否めない… LLは? 開発用ツールをLLで書くことの有用性 Perl、Python、Rubyとあるけれど… 糊として手軽である 開発効率がとってもいい 大抵のライブラリが揃っている ライブラリマネージャ(cpan、egg、gem)でネットから楽々インストール で、なんでRubyなの? 趣味です!!
https://w.atwiki.jp/ncgamereport/pages/23.html
1984/??/?? MSX PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ハッスルチュミー 仁井谷正充 仁井谷正充 仁井谷正充 【書籍】EXTRA mag. 特別増刊号(BEEP)仁井谷正充第1回インタビュー後半 コンパイルの創業・ROM内にスタッフ記名アリ。仁井谷氏以外はNISSOスタッフ?(The Cutting Room Floor) 1985/??/?? MSX PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ファイナルジャスティス 藤島聡 藤島聡 藤島聡 仁井谷正充 タイトル画面にクレジット【書籍】EXTRA mag. 特別増刊号(BEEP) 1985/06/?? PC88 PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ルナーボール 新谷憲司 新谷憲司 仁井谷正充 タイトル画面に「Lunarian」クレジットじぇみに広野氏が語るコンパイル製ゲームソフトのまめちしき(元は広野隆行氏のツイート) 1986/??/?? SG1000 PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC チャンピオンビリヤード 新谷憲司 新谷憲司 仁井谷正充佐藤秀樹(セガ) ルナーボールと同じスタッフと推測。 1986/05付近 MSX/X1 PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC バーディトライ 広野隆行 広野隆行 広野氏のツイート【書籍】EXTRA mag. 特別増刊号(BEEP)・広野氏はX1担当。MSX担当は他社? 1987/03/14 FC PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC シティアドベンチャー タッチ 石丸忠 石丸忠広野隆行 仁井谷正充 じぇみに広野氏が語るコンパイル製ゲームソフトのまめちしき 1987/12/27 MK3 PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ファミリーゲームズ 新谷憲司 新谷憲司 仁井谷正充佐藤秀樹(セガ) ルナーボールと同じスタッフと推測。 1988/09/14 PCE PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC エイリアンクラッシュ 谷田貴史 谷田貴史 迫田敏明塚本雅信 仁井谷正充 じぇみに広野氏が語るコンパイル製ゲームソフトのまめちしき 1988/12/09 FC PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ゴジラ 石丸忠 石丸忠 仁井谷正充 じぇみに広野氏が語るコンパイル製ゲームソフトのまめちしき 1990/07/20 PCE PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC デビルクラッシュ 谷田貴史 谷田貴史 迫田敏明塚本雅信 仁井谷正充 じぇみに広野氏が語るコンパイル製ゲームソフトのまめちしき 1992/12/18 SFC PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ナグザットスーパーピンボール 邪鬼破壊 塚本雅信 仁井谷正充 ・谷田貴史? 1994/10/?? AC PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC ぷよぷよ通 森田健吾 広野隆行秋山泰俊 島崎亜矢 松島剛史南智紀 仁井谷正充 ***予定*** 名前 コメント PLAN PROGRAM GRAPHIC SOUND PRODUCE ETC タイトル ○○○ ○○○ ○○○ ○○○ ○○○ ○○○ ソースとかコメントとか
https://w.atwiki.jp/powerhandle/pages/14.html
非公式ビルド ruby 関係 概要 Cygwinでzaurus用にクロスコンパイルしたものです。extディレクトリにつきましてはデフォルトで取り込まれるものとそうでないものがあります。取り込まれないライブラリは必要であれば別途導入しなければなりません。 デフォルトで取り込まれるライブラリ bigdecimal, digest, dl, etc, fcntl, iconv, io, nkf, pty, racc/cparse, sdbm, socket, stringio, strscan, syck, syslog, thread ※dlはすんなりコンパイルできていないので怪しいです 外部に依存しているか、何らかの理由で取り込まれていないライブラリ Win32API, curses, dbm, gdbm, openssl, readline, tk, win32ole, zlib ライブラリ 状況 バイナリ Win32API Linux 環境なので必要なし curses ncurses に依存 ncurses, ruby-curses dbm gdbm gdbmに依存 gdbm, ruby-gdbm openssl openssl に依存 readline ncurses, readline に依存 ncurses, readline,ruby-readline tk X と Tk があればできるかも win32ole Linux 環境なので必要なし zlib zlib に依存 zlib, ruby-zlib ダウンロード ruby本体 最新 ruby_1.8.7-p72-1_arm.ipk (1,483,840B) ruby-1.8.7 (patchlevel 72) [zaurus] md5sum 23f6d42951160e153d3cf16751cdf00d gcc version 2.95.3 20010315 (release) 旧版 拡張ライブラリ 最新 ruby-curses ruby-curses_1.8.7-p72-1_arm.ipk (16,906B) ruby-curses-1.8.7 (patchlevel 72) [zaurus] md5sum 10a7a8ecaed7fb4a25fb9a0f73313b71 gcc version 2.95.3 20010315 (release) ruby-gdbm ruby-gdbm_1.8.7-p72-1_arm.ipk (8,845B) ruby-gdbm1.8.7 (patchlevel 72) [zaurus] md5sum 3da7905b6d1191b1c8c56a6bc14861ad gcc version 2.95.3 20010315 (release) ruby-readline ruby-readline_1.8.7-p72-1_arm.ipk (7,810B) ruby-readline-1.8.7 (patchlevel 72) [zaurus] md5sum a9f355d5373e2c656ab2da725facde8e gcc version 2.95.3 20010315 (release) ruby-zlib ruby-zlib_1.8.7-p72-1_arm.ipk (16,185B) ruby-zlib-1.8.7 (patchlevel 72) [zaurus] md5sum cc812f470ca94b97c2fb0c7a36bbde17 gcc version 2.95.3 20010315 (release) 旧版
https://w.atwiki.jp/akcnv/pages/24.html
Rubyで、何らかの処理を実現するのに、どう書くのがどの程度速いのか? 姑息な最適化、高速化についての話。 注意:実行時間は環境、Rubyのバージョン等によって大幅に変わる可能性があります。 一般論 NArrayオブジェクトに対し複数条件を同時に満たす要素を効率的に得る 配列による配列のスライス結果 一般論 一度作ったオブジェクトはなるべく捨てずに使い回す。 破壊的メソッドを使う。 Array, Hashオブジェクトをclearして再利用することを考える。 C++と異なり、+=演算子は独立した演算子ではなく、 =, + 演算子のシンタックスシュガー。 NArrayオブジェクトに対し複数条件を同時に満たす要素を効率的に得る 複数条件を同時に満たす(つまり、条件1 and 条件2 and 条件3 and ...)要素を効率的に得るためのイディオムは以下の通り。 # NArrayオブジェクトaに対し、 # 複数の条件を同時に満たす要素を得るためのイディオム # 例 10以上100未満の3の要素を得る require "narray" a = NArray.to_na([15, 19, 105, 133, 81, 108, 147, 30, 98, 104, 148, 108, 2]) # 条件1 cond = a = 10 idx = cond.where # 条件2 cond = a[idx] 100 idx = idx[cond] # 条件3 cond = (a[idx] % 3).eq 0 idx = idx[cond] p a[idx] 計算効率は条件判定の順番に大きく依存する。 真である要素数が最も少ない条件を最初に持ってくるべきである。 大部分の要素が真となる場合、普通にNArray#andメソッドを使ったほうが効率的である。 cond = (a = 10).and(a 100).and((a % 3).eq 0) elem = a[cond.where] 二つの手法の効率の目安を得るため、以下のようなベンチマークを実行してみた。 require "narray" require benchmark a = NArray.int(50000) a.random! 100 # 条件1 Benchmark.bmbm(10) do |x| x.report("methodA") do 1000.times do cond = a = m idx = cond.where cond = a[idx] = 100 idx = idx[cond] elems = a[idx] end end x.report("methodB") do 1000.times do cond = (a = m).and(a = 100) elems = a[cond] end end end 0以上100未満の乱数50000要素から、m以上100未満の要素を抽出する。第二の条件は常に真であることに注意。mを様々に変えて実行した結果は以下のとおり。(数字はreal time) m = 0 methodA 1.81 methodB 0.64 m = 50 methodA 1.43 methodB 1.11 m = 70 methodA 1.06 methodB 0.98 m = 80 methodA 0.83 methodB 0.87 m = 90 methodA 0.59 methodB 0.72 第一の条件で約8割以上が偽と判定されるのであればmethodAを使ったほうが速い。 また、条件の数がさらに増えればmethodBの効率的はさらに向上するはずである。 配列による配列のスライス 与えられた配列 arr, idx に対して、 [arr[idx[0]], arr[idx[1]], ...] が欲しい場合。 考えられる方法としては mapメソッドを使う values_atメソッドを使う (配列がNArrayとして与えられている場合)NArrayでのスライスを使う が挙げられる。 require narray require benchmark n = 50000 n_arr = 100 n_idx = 1000 arr = (1..n_arr).map( to_s) idx = (1..n_idx).map {rand n_arr} na_arr = NArray.to_na(arr) na_idx = NArray.to_na(idx) Benchmark.bmbm do |b| b.report "map" do n.times { idx.map {|i| arr[i]} } end b.report "values_at" do n.times { arr.values_at(*idx)} end b.report "narray" do n.times { na_arr[na_idx] } end end 結果 (Core i7 950 @ 3.07GHz) ruby 1.8.7 (2008-08-11 patchlevel 72) [i386-cygwin] Rehearsal -------------------------------------------- map 12.246000 0.046000 12.292000 ( 12.297000) values_at 0.858000 0.016000 0.874000 ( 0.867000) narray 0.702000 0.016000 0.718000 ( 0.717000) ---------------------------------- total 13.884000sec user system total real map 11.700000 0.046000 11.746000 ( 11.752000) values_at 0.858000 0.016000 0.874000 ( 0.871000) narray 0.702000 0.016000 0.718000 ( 0.721000) ruby 1.9.1p378 (2010-01-10 revision 26273) [i386-cygwin] Rehearsal -------------------------------------------- map 5.398000 0.000000 5.398000 ( 5.412000) value_at 1.217000 0.000000 1.217000 ( 1.205000) narray 0.561000 0.000000 0.561000 ( 0.560000) ----------------------------------- total 7.176000sec user system total real map 5.414000 0.000000 5.414000 ( 5.414000) values_at 1.201000 0.000000 1.201000 ( 1.205000) narray 0.561000 0.000000 0.561000 ( 0.559000) やはりNArrayが速い。 Arrayオブジェクトに対してはvalues_atが速い。 1.9ではかなり改善されているようだが、ブロック呼び出しのためか、mapはかなり遅い。 いくらNArrayが速いからといっても、 NArray.to_na(arr)[idx] のように、わざわざNArrayオブジェクトを作ってスライスするとvalues_atよりも遅くなるので注意。