[#38371] Re: [ruby-cvs:30538] Ruby:r23320 (trunk): * lib/set.rb (SortedSet#add): Do not let an uncomparable object — "Yugui (Yuki Sonoda)" <yugui@...>
Yuguiです。
At Mon, 4 May 2009 23:44:22 +0900,
遠藤です。
At Fri, 8 May 2009 02:00:10 +0900,
[#38372] making install-sh more descriptive — "Yugui (Yuki Sonoda)" <yugui@...>
install-shが空になって久しい(r520)です。
[#38382] [Bug #1442] indentation check and coverage for toplevel do not work — Yusuke Endoh <redmine@...>
Bug #1442: indentation check and coverage for toplevel do not work
[#38390] [Bug:1.8] Tempfile and extended Enumerable — Tanaka Akira <akr@...>
1.8.8dev で、以下のように、Enumerable に each2 を定義し、
[#38392] Enumerable#gather_each — Tanaka Akira <akr@...>
ときに、複数行をまとめて扱いたいことがあります。
ujihisaと申します。
まつもと ゆきひろです
At Sun, 10 May 2009 06:00:08 +0900,
In article <E1M2t0u-0000Aa-Sd@x61.netlab.jp>,
まつもと ゆきひろです
In article <E1M4oSd-00005c-WB@x61.netlab.jp>,
In article <873ab3531u.fsf@fsij.org>,
まつもと ゆきひろです
At Sat, 9 May 2009 15:30:20 +0900,
In article <86r5yy2nrg.knu@iDaemons.org>,
At Sun, 10 May 2009 10:08:47 +0900,
In article <86ocu132gq.knu@iDaemons.org>,
At Sun, 10 May 2009 15:57:33 +0900,
In article <86my9l2tts.knu@iDaemons.org>,
Haskell の groupBy と Python の groupby が似ている、という話
遠藤です。
In article <e0b1e5700905140800y6d701c6fj731a59ffd83b9d79@mail.gmail.com>,
[#38423] longlife gc — Narihiro Nakamura <authornari@...>
nariと申します.
[#38446] [Bug:1.9] exact Time and inexact Time — Yusuke ENDOH <mame@...>
遠藤です。
In article <e0b1e5700905132145i32bed2f0y80faef19c119824f@mail.gmail.com>,
遠藤です。
[#38463] SQLiteライブラリ — "NARUSE, Yui" <naruse@...>
成瀬です。
[#38486] [Bug #1483] some commands installed without program-suffix — Kazuhiro NISHIYAMA <redmine@...>
Bug #1483: some commands installed without program-suffix
[#38493] [Feature:trunk] enhancement of Array#drop — "U.Nakamura" <usa@...>
こんにちは、なかむら(う)です。
まつもと ゆきひろです
こんにちは、なかむら(う)です。
[#38518] [Bug:1.9] Enumerator.new { }.take(1).inject(&:+) causes stack overflow — Yusuke ENDOH <mame@...>
遠藤です。
[#38524] [Bug #1503] -Kuをつけた時、/[#{s}]/n と Regexp.new("[#{s}]",nil,"n") で実行結果が異なる — sinnichi eguchi <redmine@...>
Bug #1503: -Kuをつけた時、/[#{s}]/n と Regexp.new("[#{s}]",nil,"n") で実行結果が異なる
[ruby-dev:38392] Enumerable#gather_each
ときに、複数行をまとめて扱いたいことがあります。
たとえば、RD でインデントされた部分を取り出すとか、IO のパラ
グラフモードっぽいこととか、個人的には最近 chkbuild でログの
一部をソートするという必要がありました。
しかし、Enumerable でそういうまとまりを扱うメソッドは
each_slice しかなくて、柔軟なことは出来ません。
ファイルを全部読み込んで正規表現でやるというのはひとつの案で
すが、ファイルがとても大きいかもしれないとなるとやりたくない
ことがあります。
(実際 chkbuild のログはとても大きくなることがあります)
では自分で書くか、というと、これがなかなかきれいにかけません。
例えば、インデントされた部分を取り出すにはその直後のインデン
トされていない部分まで読まないとまとまりが判断できなくて、
IO#each_line で書こうとするとけっこう面倒です。ひとつの行が
インデントされているかどうかを調べるのは行頭が空白かどうかを
調べるだけで簡単にできるのですが、その結果に従って連続した行
をまとめるのが厄介です。
ここで、インデントされているかどうかとか、パラグラフだったら
空行かどうかとか、個々の要素を分類するところは問題によって異
なるのですが、その後の分類結果にしたがって連続した要素をまとめ
るのは共通しているので、Enumerable にメソッドとしてあっても
いいんじゃないかと思います。
というわけで、Enumerable#gather_each(arg) {|ary| ... } の提
案です。引数には Proc を与えて、これは各要素について呼ばれ、
結果として分類結果を返します。gather_each はその分類結果が等
しい連続した要素を配列としてまとめて yield します。
なお、分類結果が nil というのは特別扱いで、その要素は単独で
まとまりとなることを示します。
Ruby での実装を以下に示します。
module Enumerable
def gather_each(arg)
prev_value = prev_elts = nil
self.each {|e|
v = arg.call(e)
if prev_value == nil
if v == nil
yield [e]
else
prev_value = v
prev_elts = [e]
end
else
if v == nil
yield prev_elts
yield [e]
prev_value = prev_elts = nil
elsif prev_value == v
prev_elts << e
else
yield prev_elts
prev_value = v
prev_elts = [e]
end
end
}
if prev_value != nil
yield prev_elts
end
end
end
たとえば、lib/scanf.rb には RD なドキュメントが入っていて、
以下のようにするとインデントされたコード例の部分をひとつにま
とめることができます。
arg = lambda {|l| /\A\=~ l ? true : nil }
open("lib/scanf.rb") {|f|
f.gather_each(arg) {|lines| pp lines }
}
=>
["# scanf for Ruby\n"]
["#\n"]
["# $Release Version: 1.1.2 $\n"]
...
["the return array (or yielded to the block, if a block was
given).\n"]
["\n", "\n"]
["==Basic usage\n"]
["\n",
" require 'scanf.rb'\n",
"\n",
" # String#scanf and IO#scanf take a single argument (a
format string)\n",
" array = aString.scanf(\"%d%s\")\n",
" array = anIO.scanf(\"%d%s\")\n",
"\n",
" # Kernel#scanf reads from STDIN\n",
" array = scanf(\"%d%s\")\n",
"\n"]
["==Block usage\n"]
["\n"]
...
パラグラフモードっぽく、空行で区切られた部分をまとめたいなら
以下のようにできます。
arg = lambda {|l| l == "\n" }
open("lib/scanf.rb") {|f|
f.gather_each(arg) {|lines| pp lines }
}
=>
["# scanf for Ruby\n",
"#\n",
"# $Release Version: 1.1.2 $\n",
"# $Revision: 22784 $\n",
"# $Id: scanf.rb 22784 2009-03-06 03:56:38Z nobu $\n",
"# $Author: nobu $\n",
"#\n",
"# A product of the Austin Ruby Codefest (Austin, Texas,
August 2002)\n"]
["\n"]
["=begin\n"]
["\n"]
["=scanf for Ruby\n"]
["\n"]
["==Description\n"]
["\n"]
["scanf for Ruby is an implementation of the C function
scanf(3),\n",
"modified as necessary for Ruby compatibility.\n"]
["\n"]
...
どうでしょう?
なお、複数行をまとめる方法として使いそうなものは、まとめる先
頭要素を検出する方法を指定するとか、他にもいくつかあるように
思います。たとえば ChangeLog や mbox を扱うのには、先頭要素
を指定するのがいいでしょう。そういうものはまた別のメソッドと
して作るのがいいのではないかと思います。
--
[田中 哲][たなか あきら][Tanaka Akira]