AnApprentice
AnApprentice

Reputation: 110960

Rails - IF Block with complex statements, how to optimize w/o reducing Readability?

in ruby/rails3, I need to do some heavy text parsing to find a certain string. Right now I'm doing something like the following:

extract_type1 = body.scan(/(stuff)/m).size
extract_type2 = body.scan(/(stuff)/m).size
extract_type3 = body.scan(/(stuff)/m).size
extract_type4 = body.scan(/(stuff)/m).size
extract_type5 = body.scan(/(stuff)/m).size

if extract_type1 > 0
elsif  extract_type2 > 0
elsif  extract_type3 > 0
elsif  extract_type4 > 0
elsif  extract_type5 > 0

The problem here is that I keep needing to add extract types based on the app. And that results in a lot of processing when the case occurs that extract_type1 >0 and the rest aren't needed.

But at the same time, it's nice and clean to have the extract logic separated from the if block as that would be busy messy and hard to read.

Any thoughts on how to optimize this while not compromising readability?

Thanks

Upvotes: 1

Views: 475

Answers (2)

sled
sled

Reputation: 14625

what about storing all your "keywords" you are searching for in an array and iterate over it like:

stuff   = ["stuff1", "stuff2"]

stuff.each do |c_stuff|
  if body.scan(/(#{Regexp.escape(c_stuff)})/m).size > 0
    # do something
    # break the loop
    break
  end
end    

Edit: If you need the index of the element, you can use each_with_index do |c_stuff, c_index|

Upvotes: 2

mu is too short
mu is too short

Reputation: 434665

Lazy evaluation might work for you; just convert your extract_X variables to lambdas so that the values are computed on use:

extract_type1 = lambda { body.scan(/(stuff)/m).size }
extract_type2 = lambda { body.scan(/(stuff)/m).size }
extract_type3 = lambda { body.scan(/(stuff)/m).size }
extract_type4 = lambda { body.scan(/(stuff)/m).size }
extract_type5 = lambda { body.scan(/(stuff)/m).size }

if extract_type1.call > 0
elsif  extract_type2.call > 0
elsif  extract_type3.call > 0
elsif  extract_type4.call > 0
elsif  extract_type5.call > 0

If you're using the extract_X values more than once then you can add memoization to the lambdas so that the values are computed on first access and then cached so that subsequent accesses would just use the value that was already computed.

Upvotes: 0

Related Questions