1

I was wondering what the best way is to test a string for multiple conditions.

this = "allthisstuff"

if this.include?("a")
  # then do all this stuff
end
if this.include?("f")
  # then do all this stuff too
end
if this.include?("s")
  # also do all this stuff
end

Is there a more efficient way of doing this, or is stacking if statements the best option?

sawa
  • 165,429
  • 45
  • 277
  • 381
virtual_monk
  • 120
  • 3
  • 12
  • 1
    If you care for efficiency to the last bit, don't use Rails methods. Why aren't you using the ordinary `include?`? What you are doing doesn't make sense. – sawa Feb 12 '16 at 02:04
  • 1
    What you have looks fine to me (except use `include?`). If "then do all this stuff" is short you can write ` if this.include?("a")` or ` unless this.include?("z")` – Cary Swoveland Feb 12 '16 at 02:45
  • can more than 1 condition be true? – MZaragoza Feb 12 '16 at 02:53
  • @sawa @Cary Swoveland Not sure why I added the S to `include?`. @MZaragoza - yes. in my code, quite a few of the options can be true. – virtual_monk Feb 12 '16 at 16:36

1 Answers1

1

I'd use a recursive method with callbacks.


Since you're trying to evaluate a String, you'll be best extending the String class:

#config/initializers/string.rb #-> should be in /lib 
class String
  def has? *letters
    letters.each do |letter|
      yield letter, self.include?(letter)
    end
  end
end

#app
this = "allthisstuff"
this.has?("a", "f", "s", "d") { |letter,result| puts "#{letter} #{result}" }

# -> a true
# -> f true
# -> s true
# -> d false

The above will allow you to use a single block, through which you'll be able to evaluate the passed letter:

this.has?("a", "f", "s") do |letter,result|
  if result
    case letter
      when "a"
        # do something
      when "f"
        # do something
    end
  end
end

--

If you wanted to include separate blocks (completely feasible with JS), you'd want to look at "callbacks". Although callbacks are not strictly part of the Ruby way, you may be able to do it:

#config/initializers/string.rb
class String
  def has? **letters
    letters.each do |letter,lambda|
      lambda.call(letter.to_s, self.include?(letter.to_s))
    end
  end
end

#app
this.has?({
  a: Proc.new {|letter,result| # do something },
  b: Proc.new {|letter,result| # do something else }
})

To improve this, it would be best to find the equivalent of arglist in SASS

--

Refs:

Community
  • 1
  • 1
Richard Peck
  • 76,116
  • 9
  • 93
  • 147
  • What the benefit of this over simply doing `%w(a f s).each{ |letter| if this.include?(letter) ... }`? I don't see the necessity of extending `String` here. – Mischa Feb 12 '16 at 16:47
  • I recommended extended `String` because the op asked `this.include? ....`. Could easily be a model, but would have to pass the eval object each time `has? this, "a"`. – Richard Peck Feb 12 '16 at 16:50
  • The problem with your method is that you will have to evaluate in the block. So if the OP wanted to test against 10 letters, you'd have to include the logic for each of those inside the one block. Whilst my first recommendation does the same, the second allows for individual callback methods – Richard Peck Feb 12 '16 at 16:52
  • Lastly, I wanted to give an idea as to what could be done. I've done something similar in Javascript (for Ajax), so I wanted to see if I could do it with Ruby. – Richard Peck Feb 12 '16 at 16:53