我的产品类有一个代码作为属性。代码始终是一个数字,根据产品的第一个数字是某种类型。
If first digit in 0,1,2,3 product is a 'A type'
If first digit in 4,5,6 product is a 'B type'
If first digit in 7,8,9 product is a 'C type'
我正在寻找一种在不使用3分支if
声明的情况下确定产品类型的方法。
有什么想法吗?
答案 0 :(得分:3)
面向对象的方法。显然,match?
方法可以用最符合您要求的方式编写,也可以根据您的要求进行调整 - 我在这里使用正则表达式来帮助证明这种方法的灵活性。 TYPES
常数& type_for
方法应该封装在某个地方,但这取决于你决定在哪里。
class Type
def initialize name, pattern
@name = name
@pattern = pattern
end
def match? code
code =~ @pattern
end
end
a_type = Type.new 'A', /^[0-3]/
b_type = Type.new 'B', /^[4-6]/
c_type = Type.new 'C', /^[7-9]/
TYPES = [a_type, b_type, c_type]
def type_for product
TYPES.detect { |type| type.match? product.code }
end
答案 1 :(得分:2)
您是否考虑过使用case
声明?我不确定这是否满足你想要摆脱“3分支if语句”的愿望,但也许它会给你一些别的东西来考虑。
case code[0].to_i
when 0..3 then 'A type'
when 4..6 then 'B type'
when 7..9 then 'C type'
end
我假设上面的“code”属性实际上存储为字符串,因为你指定第一个数字可以是0,而在Ruby中,如果它是一个字面整数,它会将你的数字转换为八进制。如果这是一个错误的假设,只需改变代码[0]位。
这有帮助吗?
答案 2 :(得分:1)
我倾向于在我自己的代码中使用这样的东西,因为我宁愿定义一个表格来显示与匹配值和预期输出的关系:
HASH = {
/\A[0-3]/ => 'A type',
/\A[4-6]/ => 'B type',
/\A[7-9]/ => 'C type'
}
def get_type(s)
HASH.keys.each { |regex|
return HASH[regex] if s[regex]
}
end
[ '0001', '3000', '4000', '9000' ].each do |v|
puts "#{ v } => #{ get_type(v) }"
end
哪个输出:
0001 => A type
3000 => A type
4000 => B type
9000 => C type
我尝试将类似哈希的内容保存在YAML文件中,这样我们就不必修改代码来添加其他测试/类型。可以使用YAML::load_file()
从类似于以下内容的文件轻松初始化HASH常量:
--- ? !ruby/regexp /\A[4-6]/ : B type ? !ruby/regexp /\A[0-3]/ : A type ? !ruby/regexp /\A[7-9]/ : C type
并使用简单的puts HASH.to_yaml
创建。
尽管如此,我也非常赞成case
声明方法。
答案 3 :(得分:0)
def func(code)
return 'A type' if code[0] == '0'
['A','B','C'][(code[0].to_i-1)/3] << ' type'
end
func('0ekrnn') # => 'A type'
func('4mgm') # => 'B type'
答案 4 :(得分:0)
您可以使用三元运算符
first_char = code[0].to_i
product_type = [0,1,2,3].include?(first_char) ? "A" : [4,5,6].include?(first_char) ? "B" : [7,8,9].include?(first_char) ? "C" : ""