开发者

What is the best way to handle this type of inclusive logic in Ruby?

开发者 https://www.devze.com 2023-02-04 17:21 出处:网络
Is there a better way of handling this in Ruby, while continuing to use the symbols? pos = :pos1 # can be :pos2, :pos3, etc.

Is there a better way of handling this in Ruby, while continuing to use the symbols?

pos = :pos1 # can be :pos2, :pos3, etc.

if pos == :pos1 || pos == :pos2 || pos == :pos3
  puts 'a'
end

if pos == :pos1 || pos == :pos2
  puts 'b'
end

if pos == :pos1
  puts 'c'
end

The obvious way would be swapping out the symbols for number constants, but that's not an option.

pos = 3

i开发者_如何学运维f pos >= 1
  puts 'a'
end

if pos >= 2
  puts 'b'
end

if pos >= 3
  puts 'c'
end

Thanks.

EDIT I just figured out that Ruby orders symbols in alpha/num order. This works perfectly.

pos = :pos2 # can be :pos2, :pos3, etc.

if pos >= :pos1
  puts 'a'
end

if pos >= :pos2
  puts 'b'
end

if pos >= :pos3
  puts 'c'
end


Not sure if this is the best way......

I would make use of the include? method from array:

puts 'a' if [:pos1, :pos2, :pos3].include? pos
puts 'b' if [:pos1, :pos2].include? pos
puts 'c' if [:pos1].include? pos


Just use the case statement

pos = :pos1 # can be :pos2, :pos3, etc.

case pos
   when :pos1 then %w[a b c]
   when :pos2 then %w[a b]
   when :pos3 then %w[a]
end.each {|x| puts x }


There are lots of different ways to get your output. Which one you want depends on your specific objections to your if statements. I've added a bunch of extra formatting to make the output easier to read.

If you don't like the logical ORs and how they separate the results from the output, you can use a lookup table:

puts "Lookup table 1:"
lookup_table1 = {
    :pos1 => %w{a b c},
    :pos2 => %w{a b  },
    :pos3 => %w{a    },
}
[:pos1, :pos2, :pos3].each { |which|
    puts "\t#{which}"
    lookup_table1[which].each { |x| puts "\t\t#{x}" }
}

Or, if you want all the "work" in the lookup table:

puts "Lookup table 2:"
lookup_table2 = {
    :pos1 => lambda do %w{a b c}.each { |x| puts "\t\t#{x}" } end,
    :pos2 => lambda do %w{a b  }.each { |x| puts "\t\t#{x}" } end,
    :pos3 => lambda do %w{a    }.each { |x| puts "\t\t#{x}" } end,
}
[:pos1, :pos2, :pos3].each { |which|
    puts "\t#{which}"
    lookup_table2[which].call
}

If your problem is that symbols aren't ordinals, then you can ordinalize them by converting them to strings:

puts "Ordinals by .to_s and <="
[:pos1, :pos2, :pos3].each { |which|
    puts "\t#{which}"
    if which.to_s <= :pos3.to_s
        puts "\t\ta"
    end
    if which.to_s <= :pos2.to_s
        puts "\t\tb"
    end
    if which.to_s <= :pos1.to_s
        puts "\t\tc"
    end
}

Or you could monkey patch a comparison operator into the Symbol class (not recommended):

puts "Ordinals by Symbol#<="
class Symbol
    def <= (x)
        self.to_s <= x.to_s
    end
end
[:pos1, :pos2, :pos3].each { |which|
    puts "\t#{which}"
    if which <= :pos3
        puts "\t\ta"
    end
    if which <= :pos2
        puts "\t\tb"
    end
    if which <= :pos1
        puts "\t\tc"
    end
}

Or you could use a lookup table to supply your ordinal values:

puts "Ordinals through a lookup table:"
ordinal = {
    :pos1 => 1,
    :pos2 => 2,
    :pos3 => 3,
}
[:pos1, :pos2, :pos3].each { |which|
    puts "\t#{which}"
    if ordinal[which] <= 3
        puts "\t\ta"
    end
    if ordinal[which] <= 2
        puts "\t\tb"
    end
    if ordinal[which] <= 1
        puts "\t\tc"
    end
}

Those are the obvious ones off the top of my head. It is hard to say what would be best without more specifics on what your problem with your if approach is; your second example indicates that what you really want is a way to make symbols into ordinals.


More generically, you can use this:

pos = :pos3
arr = [:pos1,:pos2,:pos3]
curr = 'a'

idx = arr.length
while idx > 0
  puts curr if arr.last(idx).include? pos
  curr = curr.next
  idx -= 1
end

Or this, for your specific example:

puts 'a'
puts 'b' if pos != :pos3
puts 'c' if pos == :pos1
0

精彩评论

暂无评论...
验证码 换一张
取 消