简体   繁体   中英

Can using the ruby flip-flop as a filter be made less kludgy?

In order to get part of text, I'm using a true if kludge in front of a flip-flop:

desired_portion_lines = text.each_line.find_all do |line|
  true if line =~ /start_regex/ .. line =~ /finish_regex/
end
desired_portion = desired_portion_lines.join

If I remove the true if bit, it complains

bad value for range (ArgumentError)

Is it possible to make it less kludgy, or should I merely do

desired_portion_lines = ""
text.each_line do |line|
  desired_portion_lines << line if line =~ /start_regex/ .. line =~ /finish_regex/
end

Or is there a better approach that doesn't use enumeration?

if you are doing it line by line, my preference is something like this

line =~ /finish_regex/ && p=0
line =~ /start_regex/ && p=1
puts line if p

if you have all in one string. I would use split

mystring.split(/finish_regex/).each do |item|
  if item[/start_regex/] 
     puts item.split(/start_regex/)[-1]
  end
end

I think

desired_portion_lines = ""
text.each_line do |line|
  desired_portion_lines << line if line =~ /start_regex/ .. line =~ /finish_regex/
end

is perfectly acceptable. The .. operator is very powerful, but not used by a lot of people, probably because they don't understand what it does. Possibly it looks weird or awkward to you because you're not used to using it, but it'll grow on you. It's very common in Perl when dealing with ranges of lines in text files, which is where I first encountered it, and eventually was using it a lot.

The only thing I'd do differently is add some parenthesis to visually separate the logical tests from each other, and from the rest of the line:

desired_portion_lines = ""
text.each_line do |line|
  desired_portion_lines << line if ( (line =~ /start_regex/) .. (line =~ /finish_regex/) )
end

Ruby (and Perl) coders seem to abhor using parenthesis, but I consider them useful for visually separating the logic tests. For me it's a readability and, by extension, a maintenance thing.

The only other thing I can think of that might help, would be to change desired_portion_lines to an array, and push your selected lines onto it. Currently, using desired_portion_lines << line appends to the string, mutating it each time. It might be faster pushing on the array then joining its elements afterward to build your string.

Back to the first example. I didn't test this but I think you can simplify it to:

desired_portion = text.each_line.find_all { |line| line =~ /start_regex/ .. line =~ /finish_regex/ }.join

The only downside to iterating over all lines in a file using the flip-flop, is that if the start-pattern can occur multiple times, you'll get each found block added to desired_portion .

true if使用!!() (触发器属于括号之间!!() ,则可以通过替换true if来保存三个字符。

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM