• 欢迎光临~

Ruby学习--Symbol和String(符号和字符串)

开发技术 开发技术 2022-05-19 次浏览

引述

刚接触Ruby时,觉得很奇怪,哎呀,为什么有的Hash对象读取,是这样的 obj[:key],有的是这样的 obj["key"],它们有什么区别呢?

符号和字符串

首先,所有:key,冒号加上一个字符串组成的变量,都叫做符号(Symbol),它是Ruby中一种特殊的类型。它最常用的场景,就是作为Hash对象的key值使用。

Symbol和String有什么不同?

相同字面量的Symbol是全局共用一个对象,而每声明一个String对象,都会创建一个新的对象;
代码示例:

puts :symbol.object_id  #906268
puts :symbol.object_id  #906268
puts "string".object_id #60
puts "string".object_id #80

所以,虽然String也可以作为Hash的key值使用,但是由于每使用一个String字面量,都会创建一个对象,在内存效率方面更推荐使用Symbol作为Hash对象的key值。

Symbol和String互相转换

:symbol.to_s
"string".to_sym

Symbol和String作为Hash的key值时,可以互相取到对方的值吗?

答案是:不可以

hash = { :symbol => "test" }
puts hash["symbol"].nil?  #true
hash = { "string" => "test" }
puts hash[:string].nil?  #true   

Symbol对于Hash的特殊声明形式

a = { symbol: "test" }
puts a["symbol"].nil?   #true
puts a[:symbol].nil?    #false
b = { "string": "test" }
puts b["string"].nil?   #true
puts b[:string].nil?    #false

证明,只要是:这样声明,而不是=>声明的Hash对象,key都会是符号

既然每一个String都是不同的对象,为什么String还可以作为Hash的key值,并保持存储中key唯一性呢

因为hash对象,比较key值是否相等,使用的是.eql?方法,等同于==

puts "string"=="string"    #true

所有变量和方法的声明,都会对应的创建一个Symbol对象。Ruby使用符号来追踪变量、方法和常量创建时的名称。

#irb下的演示
2.7.2 :001 > Symbol.all_symbols.size
 => 6303 
2.7.2 :003 > Symbol.all_symbols.grep(/rbrbrb/)
 => [] 
2.7.2 :005 > rbrbrb = 2
 => 2 
2.7.2 :006 > Symbol.all_symbols.grep(/rbrbrb/)   #这里使用grep,而不是include?("rbrbrb1") ,因为include自己会创建一个rbrbrb1符号到符号表,始终返回true,无法验证
 => [:rbrbrb] 
2.7.2 :007 > Symbol.all_symbols.size
 => 6304

PIS:'json'这个基础库解析json字符串,JSONObject会映射成Hash对象,这里的key会映射成字符串而不是symbol

require 'json'
s ='{"name":"zhangsan","age":"18"}'
puts JSON.parse(s)  #{"name"=>"zhangsan", "age"=>"18"}
程序员灯塔
转载请注明原文链接:Ruby学习--Symbol和String(符号和字符串)
喜欢 (0)