【问题标题】:Understanding hashes了解哈希
【发布时间】:2015-02-26 02:22:20
【问题描述】:

一个练习说:

创建三个名为 person1、person2 和 person3 的散列,其中第一个 和 :first:last 键下的姓氏。然后创建一个参数 哈希使得params[:father] 是person1,params[:mother] 是person2, params[:child] 是 person3。验证,例如, params[:father][:first] 具有正确的值。

我做到了

person1 = {first: "Thom", last: "Bekker"}
person2 = {first: "Kathy", last: "Bekker"}
person2 = {first: "Anessa", last: "Bekker"}

然后是 Rails 中的 params 哈希

params = {}
params[:father] = person1
params[:mother] = person2
params[:child] = person3

现在我可以像这样询问父亲、母亲或孩子的名字或姓氏 params[:father][:first] 给我"Thom"

是什么让params[:father][:first][:last] 返回错误?有没有办法让"Thom Bekker"返回?

我无法检查我想出的方法是否正确,有没有更好的方法来做这个练习?

symbol: 优于 symbol => 有什么原因吗?

【问题讨论】:

  • 社区吹毛求疵,尝试在每个帖子中坚持一个问题或对您的问题进行编号,以便我可以确保回答所有问题。 :)
  • 请在每个帖子中提出一个问题。
  • 是的,SO 严格执行只问一个问题的限制。但是,您可以发布一个单独的问题,“symbol: 是否比 symbol => 更好?”,在这种情况下,大多数响应者可能会说选择只是个人喜好问题,尽管有人可能会争辩说前者首选Code Golf
  • 仅供参考:TypeError: no implicit conversion of Symbol into Integer 是由尝试使用 :last 索引到 params[:father][:first] 引起的。使用 Integer 仍然不会做你想做的事,但至少它不会引发异常。 :)

标签: ruby hash


【解决方案1】:

您的返回值是单个哈希对象

您误解了要返回的对象的类型。 params[:father] 返回单个 Hash 对象,而不是 Array 或哈希数组。例如:

params[:father]
#=> {:first=>"Thom", :last=>"Bekker"}

params[:father].class
#=> Hash

因此,您无法访问缺少的第三个元素(例如 :last),因为在 params[:father][:first] 的值中没有这样的元素。

相反,您可以解构哈希:

first, last = params[:father].values
#=> ["Thom", "Bekker"]

或者做一些更深奥的事情,比如:

p params[:father].values.join " "
#=> "Thom Bekker"

关键是你必须访问哈希的,或者先将其转换为数组,而不是直接将其视为数组并尝试一次索引多个值。

【讨论】:

  • 你好,侏儒。我看到你从你的一次世界巡回演唱会回来了。这可能是挑剔的,但由于 OP 是新手,我认为语言准确很重要:在Hash 实例params 上调用的方法Hash#[],返回一个Hash 对象(例如,person1)。 OP应该明白,返回对象的是方法[],其中返回的对象是params[:father]的值。
  • @CarySwoveland Hash 和 Array 都有一个 #[] 方法; params 只是一个哈希,因为 OP 将其创建为带有文字的哈希(例如{})。关键是对于 OP,params[:father].class == Hash。在 Ruby 中,每个表达式都返回一个值;在这种情况下,params[:father] 的值是一个 Hash 对象,当尝试通过 Symbol 进行索引时,它是 OP(诚然是晦涩难懂的)TypeError 异常的真正来源。他真正的问题是关于如何访问数据;其余的充其量只是一次旅行。
  • 我不反对,但我只是想指出 OP(即 nit-pik),您所说的 params[:father] 返回单个 Hash 对象“它不是 ``params [:father]` 返回对象;保存由方法 [] 返回的值。如果 OP 不是新手,我不会提到它,因为大多数读者都很清楚你意思是。(但也许我只是混淆了 OP。)顺便说一句,我看到你最近在Bay Area 度过了一段时间。
【解决方案2】:

在 Ruby 中,在 Hash 或其他类上使用方括号实际上是在使用可用于该类的对象 (this one) 的方法。当您在示例中调用这些方法时,将调用这些方法中的每一个,并在调用下一个方法之前返回其结果。所以,正如你所定义的那样:

  1. params 上调用[:father] 返回person1 表示的哈希值
  2. 然后在{first: "Thom", last: "Bekker"} 上调用[:first],返回哈希中的对应值"Thom"
  3. "Thom" 上调用[:last],这会导致错误。在字符串上调用方括号,它们之间有一个整数,可以访问该索引处的字符串中的字符(person1[:first][0] 返回"T"),但"Thom" 没有办法处理其中的:last 符号方括号。

有多种方法可以让您根据需要打印名称,其中最简单的方法之一是在 person1 中组合字符串值:

params[:father][:first] + " " + params[:father][:last] 返回"Thom Bekker"

【讨论】:

  • Hash#[] 没有什么“幕后”。这只是一种看起来有点奇怪的普通方法。Ke0:把它想象成{:a => 1}.value_for_key(:a) # => 1。此外,它在一个Hash 对象,而不是 Hash 类,并且像许多方法一样,接受一个参数,这里是一个哈希键。
  • 你说得对,我已经更正了上面模糊的语言。
【解决方案3】:

所以这是我的问题,究竟是什么让 params[:father][:first][:last] 返回错误?有没有办法让它返回“Thom Bekker”?

这两种方法都可以

  1. params[:father][:first] + params[:father][:last]
  2. params[:father].values.join(' ')

但也许将它们视为嵌套结构会更好:

father = params[:father]
name   = father[:first] + father[:last]
puts name

要回答您的最后一个问题,请假设 hashrocket =>symbol: 之间没有区别。这是您不需要长时间照顾的地方。也许在第 2 年左右开始再次问这个问题,但是为了学习,把它们当作是等价的。

(完全披露,存在差异,但这是一场你真的不想看到上演的圣战)

【讨论】:

    猜你喜欢
    • 2011-06-07
    • 2023-03-18
    • 1970-01-01
    • 1970-01-01
    • 2014-09-16
    • 2020-05-04
    • 1970-01-01
    • 1970-01-01
    • 2012-03-09
    相关资源
    最近更新 更多