从数组和变量范围中提取索引
我正在运行TestFirstRuby,我一直坚持第12个问题,建立一个反向波兰表示法计算器。 我已经完成了除最后一个测试之外的所有测试,要求我取一个字符串(“1 2 3 * +”然后“1 2 3 * + 4 5 / – ”),然后评估表达式。
我要做的是将字符串转换为数组,将数字转换为整数,将运算符转换为符号,然后遍历数组并在运算符随时计算表达式。
这是代码的相关部分:
def initialize @expression = '' end def tokens(string) tokens = string.split(' ') tokens.map! { |digit| /[0-9]/.match(digit) ? digit.to_i : digit.to_sym } end def evaluate(string) #1 2 3 * + #1 2 3 * + 4 5 - / total = 0 @expression = tokens(string) @expression.map!{|item| index = @expression.index(item) if item == :+ total = total + (@expression[index-1] + @expression[index-2]) 2.times {@expression.delete_at(index-1)} elsif item == :- total = total + (@expression[index-1] - @expression[index-2]) 2.times {@expression.delete_at(index-1)} elsif item == :x total = total + (@expression[index-1] * @expression[index-2]) 2.times {@expression.delete_at(index-1)} elsif item == :/ total = total + (@expression[index-1].to_f / @expression[index-2]) 2.times {@expression.delete_at(index-1)} end } total end
我想要发生的是:对于数组中的每个项目,它检查它是否与任何符号匹配。 如果存在匹配,则将元素从符号返回两个空格,将其更改为表达式的值(因此2 3 *变为5 3 *)。 然后,我试图删除操作符和紧接在它之前的整数,只留下评估值。我这样做是通过在操作符之前的索引上运行delete_at两次(理想情况下,5 3 *转到5 *和然后只是5)。然后它将继续到数组中的下一个元素。
我认为出了什么问题,并且我无法修复:我认为这里的变量范围正在发生变化。 每次在每个循环中运行代码时,我都试图让表达式永久更改。 对于每个元素,使用@ expression.index(item)设置变量’index’。 这应该为每个循环中的每个元素重置。 我认为正在发生的是每个循环的每次迭代都会调用原始的@expression数组,而不是每个循环的每次迭代都没有。
我得到的错误是当它在第一个测试字符串(’1 2 3 * +’)的末尾到达’+’时,它试图使用:x添加,这意味着当它要求时两个变量加在一起(@exression [index-1] + @exression [index-2]),它正在拉动符号,我认为应该已经从@expression中删除了。 所以我希望评估为6 + 1被评估为3 +:x,这是行不通的。 它从原始数组中提取元素,而不是在数组改变时从数组中拉出。
希望我能够清楚地解释这一点。 任何建议都会很棒。 我认为有一些范围正在发生,但我找不到任何具体的这类问题来帮助我。 我已经尝试了不同的编码方式(.map,.each_with_index,.map.with_index等),我每次都遇到同样的问题。
你有大量的冗余代码。 特别是,您复制了四个运算符中每个运算符的运算。 这是一种更像Ruby的计算器实现方式。
码
def evaluate(string) arr = create_arr(string) until arr.size == 1 i = arr.index(arr.find { |e| e.is_a? Symbol }) arr[i-2] = arr[i-2].send(arr[i], arr[i-1]) arr.delete_at(i) arr.delete_at(i-1) end arr.first end def create_arr(string) string.split(/\s+/).map { |e| e =~ /-?[0-9]+/ ? e.to_i : e.to_sym } end
create_arr
的行也可以结束: e }
( sent
接受方法的字符串或符号),在这种情况下e.is_a? Symbol
e.is_a? Symbol
将更改为e.is_a? String
e.is_a? String
。
例子
evaluate("3 4 * 2 / 3 - 2 *") #=> 6 evaluate("10 2 / 3 + 2 / 2 -") #=> 2 evaluate("8 -2 / 1 +") #=> -3 evaluate("5 1 2 + 4 * + 3 -") #=> 14
说明
假设
string = "2 3 4 * 2 / +"
步骤1
arr = create_arr(string) #=> [2, 3, 4, :*, 2, :/, :+] arr.size == 1 #=> false v = arr.find { |e| e.is_a? Symbol } #=> :* i = arr.index(v) #=> 3 arr[i-2] = arr[i-2].send(arr[i], arr[i-1]) # arr[1] = arr[1].send(arr[3], arr[2]) # arr[1] = 3.send(:*, 4) #=> 12 arr #=> [2, 12, 4, :*, 2, :/, :+] arr.delete_at(i) #=> :* arr #=> [2, 12, 4, 2, :/, :+] arr.delete_at(i-1) #=> 4 arr #=> [2, 12, 2, :/, :+]
第2步
arr.size == 1 #=> false v = arr.find { |e| e.is_a? Symbol } #=> :/ i = arr.index(v) #=> 3 arr[i-2] = arr[i-2].send(arr[i], arr[i-1]) # arr[1] = arr[1].send(arr[3], arr[2]) # arr[1] = 12.send(:/, 2) #=> 6 arr #=> [2, 6, 2, :/, :+] arr.delete_at(i) #=> :/ arr #=> [2, 6, 2, :+] arr.delete_at(i-1) #=> 2 arr #=> [2, 6, :+]
第3步
arr.size == 1 #=> false v = arr.find { |e| e.is_a? Symbol } #=> :+ i = arr.index(v) #=> 2 arr[i-2] = arr[i-2].send(arr[i], arr[i-1]) # arr[0] = arr[0].send(arr[2], arr[1]) # arr[0] = 2.send(:+, 6) #=> 8 arr #=> [8, 6, :+] arr.delete_at(i) #=> :+ arr #=> [8, 6] arr.delete_at(i-1) #=> 6 arr #=> [8]
第4步
arr.size == 1 #=> true arr.first #=> 8
- 在rails应用程序中读取大型csv文件会占用大量内存 – 减少内存消耗的策略?
- Rails rspec undefined方法`receive_message’用于#<RSpec :: ExampleGroups ::
- 必须调用“render:layout => false”才能在Rails 2.3.3中正确呈现js.erb模板
- 如何使用Ruby维护TCP连接?
- 开始吧。 。 。 结束而表示’阻止’?
- 通过RVM在Ubuntu,Ruby 1.9.2上安装使用本机扩展的gem时出错
- 在JMS队列中使用Ruby而不是JRuby?
- 保留ActiveAdmin布局的ActiveAdmin自定义视图
- 无法让ActionMailer通过SMTP与MS Exchange一起使用