From: tamouse mailing lists Date: 2013-02-04T18:12:23+09:00 Subject: Re: Class for data analysis: File.open once On Sun, Feb 3, 2013 at 8:03 PM, Soichi Ishida wrote: > In addition to these, what if I want to apply specific regular > expressions to each of the lines? > > say, > > if line =~ /exp1/ then > # do stuff > else > # do stuff > end > > In this case, the loop for all lines must be implemented, am I correct? > > If the class methods dynamically take regular expression like > > test = DataExtractor.new('file.txt') > test.apply_regexp(/exp1/) > > Doesn't the loop need to be reactivated for each method like this? This last bit would be true in most cases, but you'd be looping through the lines of the file in memory rather than re-reading it. This sounds like a great case for using an Enumerable mixin: class Dataanalysis include Enumerable attr_reader :lines attr_reader :emptylines def initialize(filename) @filename = filename @content = File.readlines(@filename) @lines = @content.size @emptylines = @content.grep(/^\s*$/).size end def each(&b) @content.each do |line| if block_given? b.call line else yield line end end end end Then you can do fun things like: 1.9.3-head :034 > f = Dataanalysis.new('dataanalysis.rb') => # 1.9.3-head :035 > f.lines => 23 1.9.3-head :036 > f.emptylines => 3 1.9.3-head :040 > f.each{|l| puts l.gsub(/\s+/,'*')} class*Dataanalysis* *include*Enumerable* *attr_reader*:lines* *attr_reader*:emptylines* * *def*initialize(filename)* *@filename*=*filename* *@content*=*File.readlines(@filename)* *@lines*=*@content.size* *@emptylines*=*@content.grep(/^\s*$/).size* *end* * *def*each(&b)* *@content.each*do*|line|* *if*block_given?* *b.call*line* *else* *yield*line* *end* *end* *end* * end* 1.9.3-head :041 > f.map{|l| l.gsub(/\s+/,'*')} => ["class*Dataanalysis*", "*include*Enumerable*", "*attr_reader*:lines*", "*attr_reader*:emptylines*", "*", "*def*initialize(filename)*", "*@filename*=*filename*", "*@content*=*File.readlines(@filename)*", "*@lines*=*@content.size*", "*@emptylines*=*@content.grep(/^\\s*$/).size*", "*end*", "*", "*def*each(&b)*", "*@content.each*do*|line|*", "*if*block_given?*", "*b.call*line*", "*else*", "*yield*line*", "*end*", "*end*", "*end*", "*", "end*"] and so on. All this said, there is still a caveat: the size of the file under analysis. If it's something smallish to medium, no problem. If it's a 4G log file -- then you'll likely have some issues.