从一个数组和变量的作用域拉指数 [英] Pulling indexes from an array and variable scope

查看:107
本文介绍了从一个数组和变量的作用域拉指数的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我通过TestFirstRuby跑,我一直停留在12的问题,建立逆波兰式计算器。我已经通过所有除了最后一个测试得到,要我取字符串(1 2 3 * +,然后选择1 2 3 * 4 + 5 / - ),然后评估前pression。

I'm running through TestFirstRuby and I've been stuck on problem 12, building a Reverse Polish Notation calculator. I've gotten through all of the tests except for the last one, asking me to take a string ("1 2 3 * +" and then "1 2 3 * + 4 5 / -"), and then evaluate the expression.

我想要做的就是将字符串转换为一个数组,改变了数字到整数,运营商为符号,然后再通过数组和评估前pression任何时候涉及到运营商。

What I'm trying to do is convert the string to an array, changing the numbers into integers and the operators into symbols, then go through the array and evaluate the expression anytime it comes to an operator.

这里的code的相关部分:

Here's the relevant part of the code:

  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

我希望发生的是这样的:数组中的每个项目,它会检查它是否匹配任何符号。如果有一个匹配,它改变了从元素符号两个空格回的任何前任pression是值(SO 2 * 3变为5 3 *)。然后,我米试图之前立即删除操作和整数,只留下评估值。我通过在指数运行delete_at两次就在运营商面前做这个(理想情况下,5个3 *去5 *和然后只需5)。然后,它会移动到阵列中的下一个元素。

What I WANT to happen is this: for each item in the array, it checks if it matches any of the symbols. If there's a match, it changes the element two spaces back from the symbol into the value of whatever the expression is (so 2 3 * becomes 5 3 *). Then, I"m trying to delete the operator and the integer immediately before it, leaving only the evaluated value. I'm doing this by running delete_at twice on the index just before the operator (ideally, 5 3 * goes to 5 * and then just 5). Then it'll move on to the next element in the array.

我觉得这是怎么回事错了,我遇到了麻烦固定:我认为有些事情是怎么回事的变量范围。我试图让前pression永久性地改变了每一个在其上运行它目前在每个循环的任何元素code时间。对于每一个元素,一个变量索引是使用前@ pression.index(项目)设置。这应该重置在每个循环中的每个元素。我认为,这是怎么回事的是,原本前@ pression数组被称为对每个循环的每个迭代,从每个循环的每次迭代不变。

What I THINK is going wrong, and am having trouble fixing: I think something's going on with the variable scope here. I'm trying to get the expression to be permanently changed every time it runs the code on whatever element it's currently on in the each loop. For each element, a variable 'index' is set using @expression.index(item). This should reset for each element in the each loop. I THINK what's going on is that the original @expression array is being called on for each iteration of the each loop, unchanged from each iteration of the each loop.

我收到的错误是说,当它在第一测试字符串的末端到达的+('1 2 3 * +),它试图使用添加:X,意思​​是当它的呼吁两个变量相加(@前pression [索引1] + @前pression [指数-2]),它拉动的象征,我认为应该是从@前$删除p $ pssion了。那么,我希望为6 + 1被评价为3 +将评估:X,这是行不通的。它的牵引元素从原来的阵列,而不是从因为它改变了阵列中拔出。

The error I'm getting is saying that when it gets to the '+' at the end of the first test string ('1 2 3 * +'), it's trying to add using :x, meaning that when it's calling for the two variables to add together (@expression[index-1] + @expression[index-2]), it's pulling the symbol, which I thought should have been deleted from @expression already. So what I'm hoping will evaluate as 6 + 1 is being evaluated as 3 + :x, which wouldn't work. It's pulling elements from the original array, instead of pulling from the array as it's changed.

希望我解释这显然不够。任何意见将是巨大的。我想有一些与范围怎么回事,但我找不到具体到这类问题任何事情来帮助我。我试过这种编码方式不同(.MAP,.each_with_index,.map.with_index,和其他人),每一次我得到了同样的问题。

Hopefully I'm explaining this clearly enough. Any advice would be great. I'm thinking there's something with scope going on, but I can't find anything specific to this kind of problem to help me out. I've tried different ways of coding this (.map, .each_with_index, .map.with_index, and others), and I'm getting the same problem each time.

推荐答案

您有多余的code的大量。特别是,你的复制操作的四个运营商。这里是实现你的计算器更红宝石般的方式。

You have a tremendous amount of redundant code. In particular, you replicate the operations for each of the four operators. Here is a more Ruby-like way of implementing your calculator.

code

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.is_a?符号将改为 e.is_a?字符串

The line in create_arr could alternatively end : e } (sent accepts a string or symbol for the method), in which case e.is_a? Symbol would be changed to 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

这篇关于从一个数组和变量的作用域拉指数的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆