ruby - 对使用符号符号进入 Ruby Hash 内部的百万种方法感到困惑

标签 ruby hash

我正沉浸在数百万种访问 Hash 的方法中。

condition1 = {
    "e" =>1
}

condition2 = {
    "e":1
}

condition3 = {
    :"e" =>3
}


condition4 = {
    e:4
}


condition5 = {  # 100% sure not working because of syntax error
    e=>5
}

condition6 = {  # 100% sure not working because of syntax error
    :e:6
}  

condition7 = {
    :e=>7
}

puts condition1["e"]
puts condition2["e"]
puts condition3[:e]
puts condition4[:e]
puts condition7[:e]

输出:

1
                                     (nothing)
3
4
7

第一个问题:对于前 2 个 puts 语句, 为什么它对第一个有效而不对第二个有效?在这两个哈希中,我都使用字符串作为键。是不是因为我在第一个哈希中使用了“=>”,因此字符串实际上被读取为符号?所以它实际上是像这样处理的:“e”=> 1?

第二个问题:这引出了我关于第三个条件的第二个问题,我被告知如果我在引号前使用 Symbol 符号,在后台发生的是引号将被忽略。这就是为什么我能够简单地通过 :e 访问它而无需引号。真的吗?但是,如果这是真的,那么第一个问题就会变得更加困惑。如果在第一个条件下,“e”=>1 被评估为:“e”=>1,那么不应该忽略引号吗?因此最终它被读作 :e =>1。那我怎么只用引号就可以访问它呢?

第三个问题:那么如何访问第二个条件?我知道不建议使用字符串作为键值。但是,如果在某种情况下我已经用字符串创建了它,我该如何访问它呢?我尝试通过变量名访问它,但它仍然没有输出任何内容。

非常感谢您阅读本文。我知道太在意这些细节是绝对不值得的。但我今天遇到了它,如果不弄清楚到底发生了什么,我就无法继续前进!!

最佳答案

经验法则

If there's a colon (:) it's a Symbol. If there's a hashrocket (=>), it's whatever is to the left of the hashrocket (which can be anything).

在哈希文字中声明键

当我们说“哈希文字”时,我们指的是用大括号 ({ foo: 1 }) 或作为方法参数 (bar(baz: 2)) 声明哈希的代码。

有两种方法可以在哈希文字中声明键。

带 hashrockets 的键 ( => )

声明 key 的第一种方法是使用 hashrocket ( => )。当您使用 hashrocket 时,键是它左边的任何值,您可以将任何类型的对象(或表达式)放在它的左边:

hashrocket_hash = {
  "I am a String" => 1,
  :I_am_a_Symbol => 2,
  :"I am also a Symbol" => 4,
  /I am a Regexp!/ => 5,
  Kernel => 6,
  if true then "I am also a String" end => 7,
  nil => 8
}

p hashrocket_hash.keys
# => [ "I am a String",
#      :I_am_a_Symbol,
#      :"I am also a Symbol",
#      /I am a Regexp!/,
#      Kernel,
#      "I am also a String",
#      nil
#    ]

p hashrocket_keys.map(&:class)
# => [ String,
#      Symbol,
#      Symbol,
#      Regexp,
#      Module,
#      String,
#      NilClass
#    ]

带冒号的键 ( : )

声明 key 的另一种方法是使用冒号 ( : )。当您使用冒号时,生成的键总是是一个符号。通常的符号规则适用(在这里阅读非常详尽的答案:What can a ruby symbol (syntax) contain?)除了冒号在末尾而不是开头:

colon_hash = {
  I_am_a_Symbol: 9,
  "I am also a Symbol": 10
}

p colon_hash.keys
# => [ :I_am_a_Symbol,
#      :"I am also a Symbol" ]

p colon_hash.keys.map(&:class)
# => [ Symbol,
#      Symbol ]

访问哈希值

访问哈希值没有特殊规则。如果要访问其键为 Symbol 的值,则必须使用 Symbol。如果要访问其键为字符串的值,则必须使用字符串。如果 key 是其他东西,则必须使用那个东西。

在下面的示例中,请密切注意哪些键后跟冒号,哪些键后跟 hashrockets:

hsh1 = { foo: 1 }
p hsh1[:foo]   # => 1
p hsh1[:"foo"] # => 1
p hsh1["foo"]  # => nil

hsh2 = { "bar": 2 }
p hsh2[:bar]   # => 2
p hsh2[:"bar"] # => 2
p hsh2["bar"]  # => nil

hsh3 = {
  Kernel: 3,
  Kernel => 4
}
p hsh3[:Kernel]  # => 3
p hsh3[Kernel]   # => 4
p hsh3["Kernel"] # => nil

关于ruby - 对使用符号符号进入 Ruby Hash 内部的百万种方法感到困惑,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/37759356/

相关文章:

ruby-on-rails - 在 Windows 7 x64 上安装 Ruby and Rails 和 DevKit 时出现问题 - 需要修复

ruby-on-rails - 如何干掉使用 'Module'的资源路由

ruby - 尝试安装 Ruby 1.9.3-p547 退出并出现警告 : unrecognized options: --with-libyaml-dir, --with-readline-dir

java - Cassandra = 内存/编码- key 占用空间(哈希/字节[]=>十六进制=>UTF16=>字节[])

mysql - 在 MySQL 数据库 : Hash vs Encryption? 上存储密码

ruby - 安装 Ruby Gem 不适用于 OSX 10.10 Yosemite

ruby - 正则表达式:将 url 字符串的两个斜杠之间的倒数第二个值作为子字符串

javascript - Android Webview,formhash 在某些 Android 设备上不工作

c++ - 如何在不更改其键的情况下增加哈希表的特定值?

Ruby 解析输入文件并放入哈希