Ruby 我如何构建一个基本的';英语计算器&x27;用红宝石?
因此,我目前正在这个优秀的网站上进行Ruby培训,遇到了一个比我的水平略高的问题,但我觉得如果我能看看/a答案并将其在我的大脑中循环一段时间,它真的可以帮助我的代码开发。一种缺少链接类型的交易 问题是如何构建Calc类以实现以下结果:Ruby 我如何构建一个基本的';英语计算器&x27;用红宝石?,ruby,oop,method-chaining,Ruby,Oop,Method Chaining,因此,我目前正在这个优秀的网站上进行Ruby培训,遇到了一个比我的水平略高的问题,但我觉得如果我能看看/a答案并将其在我的大脑中循环一段时间,它真的可以帮助我的代码开发。一种缺少链接类型的交易 问题是如何构建Calc类以实现以下结果: class Calc end Calc.new.one.plus.two # Should return 3 Calc.new.five.minus.six # Should return -1 Calc.new.se
class Calc
end
Calc.new.one.plus.two # Should return 3
Calc.new.five.minus.six # Should return -1
Calc.new.seven.times.two # Should return 14
Calc.new.nine.divided_by.three # Should return 3
该类只需要处理单个数字输入零9和+-*/运算符,并且格式将始终是一个由3个方法组成的链,如您所见(即数字运算符编号)
我很乐意阅读你的一些解决方案,如果你不介意的话,还可以阅读你在解决问题时所经历的思考过程。谢谢 假设这些方法不会以无效方式使用:
class Calc
def self.operand name, v
define_method(name) do
@operator ? @operand.send(@operator, v) : (@operand = v; self)
end
end
def self.operator name, v
define_method(name) do
@operator = v; self
end
end
operand :one, 1
operand :two, 2
...
operator :plus, :+
operator :minus, :-
...
end
这里还有一个技巧: 我并没有完全实现它。但是你可以从中得到一个想法,对于你的情况。这个怎么样
class Calc
attr_accessor :result, :last_operator
def initialize(result=0)
@result = result
end
OPERATORS = {
:plus => :+, :minus => :-, :times => :*, :divided_by => :/
}
OPERANDS = [ :zero, :one, :two, :three, :four, :five, :six, :seven, :eight, :nine, :ten, :eleven, :twelve ]
def method_missing(m, *args, &block)
if OPERATORS.include?(m.to_sym)
@last_operator = m.to_sym
return self
elsif OPERANDS.include?(m.to_sym)
if @last_operator.nil?
@result = OPERANDS.index(m.to_sym)
return self
end
@result = eval("#{@result} #{OPERATORS[@last_operator]} #{OPERANDS.index(m.to_sym)}")
return @last_operator.nil? ? self : @result
end
super
end
end
[20] pry(main)> Calc.new.three.times.seven
=> 21
[21] pry(main)> Calc.new.twelve.divided_by.two
=> 6
不是最佳解决方案,但满足以下要求:
class Calc
ENGLISH_TO_OP = Hash[%i{zero one two three four five six seven eight nine}
.each_with_index.to_a].merge(plus: :+, minus: :-, times: :*, divided_by: :/)
def method_missing(m)
if s = ENGLISH_TO_OP[m]
(@cmd ||= []) << s
return @cmd[0].send(*@cmd[1..2]) if @cmd.size == 3
self
else
super
end
end
end
我不想写太多的代码,因此
method\u missing
比必须定义方法要好得多,尽管它可能会有问题,因此我倾向于避免它。散列查找适用于指定的操作数和操作,并且每个带有\u索引的\u
都可以填充值。在条件中为s赋值就是懒惰。最后,我可以在初始化器中初始化@cmd
,但这是较少的代码,可以防止@cmd
稍后被另一种方法重置为零。虽然我认为这通常是一个好问题(也是一个有趣的问题),不幸的是,Stackoverflow并不是解决这样一个相当广泛的问题的好地方。因此,更多的是具体的问题和答案;可以简明扼要地回答的事情,等等。我想你可能会在某种论坛上更幸运。或者,你可以尝试一些想法,如果你遇到一个问题或一个以前没有在这里回答过的特定问题,你肯定可以发布它。这更多的是一个讨论的请求,而不是一个可回答的问题,正如@teeg所说,这与StackOverflow的目的背道而驰我已经解决了这个关于codewars的kata,如果将整个kata作为一个问题来提问,那么根本不符合尝试kata的目的,您应该尝试kata,当您遇到问题时,发布您遇到的问题。这将打印值,而无需调用外部方法。如果希望嵌套更多调用,则必须为fixnum执行方法_missing,并且可能必须覆盖“times”(因为fixnum已经有times)。。这个解决方案完全解决了你的问题(虽然=)哈哈。。我相信你最终会做一些疯狂简单的事情!(检查下面@GarySWeaver的解决方案)他认为这些运算符都是二进制运算符。是的。。他使用了一种不同的(有趣的)方式。是的,非常简单,最后调用val
:-)@Abdoself
是这里的主要思想,每次方法调用后我都会返回它。:)最后一个val
就像在计算器上按等号一样。我不认为当你不能使用val
时,self
是主要的想法(因为最后,你不能返回预期的输出)@Abdo这实际上是我的救命稻草……)我该如何改进它呢?哈哈:-)你必须将无休止的链接限制为三个(否则,必须使用monkeypatch Fixnum)。。。检查下面的代码=)
class Calc
ENGLISH_TO_OP = Hash[%i{zero one two three four five six seven eight nine}
.each_with_index.to_a].merge(plus: :+, minus: :-, times: :*, divided_by: :/)
def method_missing(m)
if s = ENGLISH_TO_OP[m]
(@cmd ||= []) << s
return @cmd[0].send(*@cmd[1..2]) if @cmd.size == 3
self
else
super
end
end
end
2.1.0 :015 > Calc.new.seven.times.two
=> 14
2.1.0 :016 > Calc.new.nine.divided_by.three
=> 3
2.1.0 :017 > Calc.new.five.minus.six
=> -1
2.1.0 :018 > Calc.new.one.plus.two
=> 3