【问题标题】:Help explaining symbols as hash values in Ruby?帮助将符号解释为 Ruby 中的哈希值?
【发布时间】:2011-11-07 05:07:27
【问题描述】:

总红宝石菜鸟。我正在通过 Zed Shaw 的 LRTHW,并且我被困在 Hash 练习中。我无法理解这段代码,并且在网络上找不到任何看起来像它的东西。

cities = {'CA' => 'San Francisco', 'MI' => 'Detroit', 'FL' => 'Jacksonville'}

cities['NY'] = 'New York'
cities['OR'] = 'Portland'

def find_city (map, state)
  if map.include? state
    return map[state]
  else
    return "Not found."
  end
end

cities[:find] = method(:find_city)

while true
  print "State? (Enter to quit) "
  state = gets.chomp

  break if state.empty?

  puts cities[:find].call(cities, state)
end

基本上,我只是卡住了。我无法在我输入一个州的方式和它返回城市之间建立联系。任何愚蠢的解释将不胜感激。

【问题讨论】:

  • 这段代码看起来不像是为了清楚起见而写的。也许它是为了演示 ruby​​ 的某些特定部分而编写的,例如 method 方法? map 参数应重命名为哈希。无需使用method; Zed 可以在他的 while 循环中简单地调用 find_city。如果他真的想,他可以在哈希表上添加find作为Singleton方法,那么你不需要map参数(只使用self)。
  • 如果您正确引用找到代码的网站/书籍并告诉我们您不理解的第一行代码是什么,这将是一个更好的问题。

标签: ruby hash symbols


【解决方案1】:

这里有一个带有 3 对键 => 值的哈希(城市)

cities = {'CA' => 'San Francisco', 'MI' => 'Detroit', 'FL' => 'Jacksonville'}

您可以通过键访问该值:

puts cities['CA']  #=>  'San Francisco'

现在我们添加两个新的对。

cities['NY'] = 'New York'
cities['OR'] = 'Portland'

整个哈希将是:

p cities #=> {'CA' => 'San Francisco', 'MI' => 'Detroit', 'FL' => 'Jacksonville', 'NY' => 'New York', 'OR' => 'Portland'}

现在它定义了一个名为find_city 的方法。它需要一个哈希和一个密钥。

def find_city (map, state)
  # if hash has the key, return its value. (There are better ways to do it.)
  if map.include? state
    return map[state]
  else
    return "Not found."
  end
end

这是我见过的最糟糕的 Ruby 代码。

cities[:find] = method(:find_city)

好的,该代码获取方法 find_city 并将其转换为 Method 对象,可以将其分配给变量。但是,它不是使用普通的局部变量,而是存储在 cities 哈希值中!

该对象类似于方法,但它是对象而不是方法,并且必须使用call 调用(在 Ruby 1.8.7 中)。

我将使用一个名为my_meth(可以是任何名称)的变量来更好地解释。

# get the method find_city and turns it into an object assigned to my_meth
my_meth = method(:find_city)

while true
  print "State? (Enter to quit) "
  state = gets.chomp

  break if state.empty?

  # here we use find_city on the cities hash.
  puts my_meth.call(cities, state)
end

puts my_meth.class

但是,为了使用变量,原始代码将 Method 对象存储在 cities 哈希上。因此,城市将是:

cities[:find] = method(:find_city)
p cities #=> {'CA' => 'San Francisco', 'MI' => 'Detroit', 'FL' => 'Jacksonville', 'NY' => 'New York', 'OR' => 'Portland', :find => (the Method object)}

因此,您可以通过cities[:find].call 访问find_city

【讨论】:

  • @pst 你是对的!我已经编辑了我的答案以更正它。谢谢!
【解决方案2】:

一个符号代表它自己,就像0代表0一样——一个符号只等于它自己。 (考虑:foo == "foo" 为假,所以hash[:foo] 永远不能引用hash["foo"] 对,即使两者可能评估为同一个对象。

所以cities[:find] 没有多大意义,它会将数据(哈希映射到大城市的状态)与对数据的操作混淆......它也可能是cityFindFunction。但是,因为使用方法本身就可以了(这里不需要转换为函数!),请考虑以下简化:

cities = {'CA' => 'San Francisco', 'MI' => 'Detroit', 'FL' => 'Jacksonville'}

def find_city (map, state)
  if map.include? state
    # if this hash contains the state, e.g. "CA" then
    # return a big city in the state
    return map[state]
  else
    # otherwise return a diagnostic message
    return "Not found."
  end
end

while true
  print "State? (Enter to quit) "
  state = gets.chomp

  break if state.empty?

  # this is a method invocation, no need for "call"!
  puts find_city(cities, state)
end

这可以通过返回 nil 而不是“未找到”来进一步简化。 (让调用者处理它)或使用哈希的默认值。无论如何,我希望以上内容能说明正在做的事情的“本质”。

编码愉快。


关于方法与方法与功能的简要说明。

在 Ruby 中,方法不是一等值。相反,它们是给定对象做出反应的“消息”。上面的find_city(cities, state) 方法调用self.__send__(:find_city, cities, state) 很方便。 (嗯,并不是因为__send__ 本身就是一个方法调用,但这是内部发生的事情的要点...... ;-)

函数Proc 类型)和Method 类型的对象,另一方面,只是对象。因此,与方法不同,它们是“一流的价值观”。要调用/应用 Function/Method 对象,请使用call methodFunction/Method ) 它使用给定的参数执行函数并计算出 Functions/Methods 返回值。

method 方法返回一个方法对象 -- 绑定到对象实例method被调用 --对于给定的方法

希望能解释一下其余部分 ;-)

【讨论】:

  • 哇,我不敢相信这有多大帮助!非常感谢。
  • 我想我几乎已经把这一切都整理好了,你的回答真的很有帮助。你能解释一下 find_city 方法的“map”参数到底在做什么吗?我不确定我是否正在建立连接,该方法是如何从城市哈希中提取值的。
  • @anatomyofashane 函数内的map 变量对应于cities 哈希:包含州/城市的哈希对象,这是评估@ 的结果987654339@ 变量,在方法调用时,被分配给map 函数参数。
【解决方案3】:

没那么难。

  • 前 4 行用缩写 => 州名填写您的哈希
  • 然后定义一个方法 find_city,它获取地图和缩写并打印相应的名称。
  • 之后,您将名为 find_city 的方法放在带有键 :find 的哈希城市中。
  • cities[:find].call(cities, state) 只是使用参数调用之前保存的方法。

您可以至少在哈希部分使用字符串或整数,而不是在这里使用符号。此外,您可以使用 method("find_city") 而不是 method(:find_city)

您只需要了解基本的 ruby​​ 逻辑,并且可以将方法引用为对象。

【讨论】:

    猜你喜欢
    • 2011-04-17
    • 2011-03-24
    • 2017-07-27
    • 2014-09-20
    • 2019-05-07
    • 1970-01-01
    • 2014-05-23
    • 2012-03-31
    • 1970-01-01
    相关资源
    最近更新 更多