ruby on rails安装(红袖添香,绝代妖娆,Ruby语言基础入门教程之Ruby3基础数据类型(data types)EP02)
Ruby是强类型动态语言 ,即Ruby中一旦某一个对象被定义类型 ,如果不通过强制转换操作 ,那么它永远就是该数据类型 ,并且只有在Ruby解释器运行时才会检测对象数据类型 ,它的一切皆为对象(包括 nil 值对象) ,可以通过调用内置class属性来获取该对象的具体数据类型 。对于 Ruby 而言 ,所有类型都继承自 Object 类(根类为 BasicObject) 。
数字(Numeric)
数字是最基本的数据类型之一 ,Ruby 中包含五种内置数字类型类: Numeric, Integer, Float, Fixnum 和 Bignum, 另外标准库中还提供了三种数字类型:Complex, BigDecimal, Rational. 除 Numeric 类外其他数字类型类都继承自 Numeric 。
irb(main):005:0> 100.class => Integer irb(main):004:0> Integer.superclass => Numeric31位以内的整数为 Fixnum, 超过31位的数为Bignum, Bignum 没有位数限制 ,可以理解为长整形 。
Ruby3支持基本的数学运算符(+, -, *, /) ,及取余(%), 求指数(**) ,等 。
所有数字对象为不可变对象 ,因此 Ruby中没有自增和自减操作符(++, –):
irb(main):006:0> x = 4/2 => 2 irb(main):007:0> y = 6.0/2 => 3.0 irb(main):008:0> x**2 => 4 irb(main):009:0> x**-1 => (1/2) irb(main):010:0> x**(1/2.0) irb(main):011:0> x**(1/3) => 1 irb(main):012:0> x => 2在Ruby中,一元运算符+= 、 -= 、 *=等其它类似的操作 ,和对应的二元运算x = x + y是完全等价的 ,都会创建新的对象x 。其它语言中,可能一元操作符是原处修改的 ,对应的二元运算是非原处修改的 ,所以其它语言中使用一元运算方式效率可能会稍高一些 ,但Ruby中是等价的 ,所以说变了 ,一元运算符在Ruby中的作用仅仅是减少代码量 ,而并非有性能优化的空间 。
对于浮点数来讲 ,Ruby提供了BigDecimal类来解决精度丢失问题 ,使用该类可以按实际值运算 ,但效率上不占优势:
irb(main):013:0> require bigdecimal irb(main):014:0> BigDecimal(0.2) - BigDecimal(0.1) === BigDecimal(0.1) => true字符串(String)
普通字符串对象通常以双引号的形式声明 ,可转义字符 ,单引号原样输出不转义 ,字符串还可以包含变量或表达式(内嵌 #{ expr }):
irb(main):017:0> "360 degrees = #{2*Math::PI} radians" => "360 degrees = 6.283185307179586 radians"注意#{ expr }方式需要双引号引用 。
也像Python那样可以使用类似通配符的方式格式化输出:
irb(main):022:0> "%s: %f" % ["pi", Math::PI] => "pi: 3.141593"和其他语言不同的是,Ruby3中的字符串是可变对象:
irb(main):028:0> ss = "123" => "123" irb(main):029:0> ss[0] => "1" irb(main):030:0> ss[0] = "2" => "2" irb(main):031:0> ss => "223"也就是说 ,如果我们定义了一个字符串 ,可以随时通过下标对字符串中的字符进行修改,而Python或者Golang中的字符串是不可变对象 ,所以只能通过重新赋值的方式进行修改 。
常用的字符串方法:
# 获取字符串长度 "Hello".length #=> 5 "Hello World!".length #=> 12 # 判断字符串是否为空 "Hello".empty? #=> false "!".empty? #=> false " ".empty? #=> false "".empty? #=> true # 检索字符数量 "HELLO".count(L) #=> 2 "HELLO WORLD!".count(LO) #=> 1 # 插入字符串 "Hello".insert(3, "hi5") #=> Helhi5lo # "hi5" is inserted into the string right before the second l which is at index 3 # 转大写 "Hello".upcase #=> HELLO # 转小写 "Hello".downcase #=> hello # 交换大小写 "hELLO wORLD".swapcase #=> Hello World # 字符串翻转 "Hello World!".reverse #=> "!dlroW olleH" # 字符串切割数组 "Hello, how are you?".split #=> ["Hello,", "how", "are", "you?"] # 字符删除 name = "Batman" name.chop name == "Batma" #=> false # 清除空格 " Hello ".strip #=> Hello # 强转整形 "15".to_i #=> 15 # integer # 字符串拼接 "15" + "15" #=> "1515" # string "15" << "15" #=> "1515" # string "15".concat "15" #=> "1515" # string # 获取字符索引 "information".index(o) #=> 3 "information".index(mat) #=> 5 "information".index(/[abc]/) #=> 6 "information".index(o, 5) #=> 9 "information".index(z) #=> nil可以看到 ,全部由字符串内置属性完成 ,并不需要外部方法的参与 。
与此同时 ,还可以通过对象的的frozen?属性判断类型是否可变 。
irb(main):035:0> "123".frozen? => false irb(main):036:0> 3.frozen? => true返回true为不可变对象 ,而false则代表可变 。
符号(symbol)
符号(symbol)和字符串很相似 ,符号也是对象 ,一般作为名称标签来使用 ,用来表示变量等对象的名称 ,另外符号和字符串可以相互转换。
声明符号:
#声明symbol对象 :test1 :test其实就是字符串前面加个冒号: 就是符号 。
字符串和符号区别:
#可以通过object_id方法来获得一个对象的标识符 test1.object_id =>70201737198340 test1.object_id =>70201752605900 test1.object_id =>70201752351880 :test2.object_id =>8869148 :test2.object_id =>8869148 :test2.object_id =>8869148在Ruby3中每一个对象都有唯一对象标识符 ,也可以理解为内存地址标识 ,每个字符串对象都是不同的 ,即使它们包含了相同的字符串内容,而对于符号对象 ,相同的字符串内容则只会指向唯一确定的一个符号对象 ,这样实际上节约了内存,减少了性能损耗 。
符号不可以像其他变量一样对它进行赋值运算。比如这样的写法是错误的:myname = "test" 。 相反符号可以作为值赋给其他变量比如mystring = :myname 。
所有符号对象存放在 Ruby内部的符号表中 ,可以通过类方法 Symbol.all_symbols 得到当前 Ruby 程序中定义的所有 Symbol 对象 ,该方法返回一个 Symbol 对象数组 。
符号与字符串相互转换:
var1 = "test".to_sym #=>:test var1 = :test.to_s #=>"test"一般情况下 ,符号作为哈希的key进行取值操作 ,这样效率和性能更高:
H = Hash[:"a" => 100, :"b" => 200] puts H[:a]程序返回:
100因为 Ruby3对每一次字符串引用都会生成一个字符串对象 ,累积下来这个开销是相当大的 。
需要注意的是 ,符号是不可变对象 。
哈希(Hash)
哈希是一种非常有用且广泛使用的复合容器对象 ,可用于存储其他对象 。我们通过键(key)来查找哈希中的值(value) 。好比我们有一个牛津词典 ,我们通过查找“hello的单词来找到中文意思"你好" ,此时 ,“hello“就是作为键 ,而“你好 ”就是值 。
声明哈希:
H = {}可以单独对key和value进行赋值操作:
H[:a] = "123" puts H[:a]也可以通过使用=>将键分配给值来创建哈希 ,用逗号分隔多个键值对,并用花括号将整个内容括起来:
H = { "one" => "1", "two" => "2", "three" => "3" } puts H直接通过key就可以进行取值 、修改等操作:
puts H["one"]当我们查找的键没有对应内容时 ,会返回一个nil 。
也可以使用fetch方法 ,他和[]方法一样都可以查找某一个键的值,但是如果键对应的值不存在 ,会抛出异常 。
哈希可以进行合并操作:
a = { "one" => "eins" } b = { "two" => "zwei" } puts a.merge(b) puts a通过keys方法打印所有的键:
H = {} H[:a] = "123" puts H.keys()也可以通过values返回一个带有哈希所有值的数组:
H = {} H[:a] = "123" H["123"] = "123" puts H.values()判断哈希是否为空:
{}.empty? # ---- 输出结果 ---- true也可以使用size或者length方法 ,判断哈希的大小是否为0:
dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" } puts dictionary.size == 0 puts dictionary.length == 0 # ---- 输出结果 ---- false false通过delete方法删除键值对:
dictionary = { "one" => "eins", "two" => "zwei", "three" => "drei" } dictionary.delete("one") puts dictionary # ---- 输出结果 ---- {"two"=>"zwei", "three"=>"drei"}需要注意的是 ,哈希是可变对象:
irb(main):041:0> {}.frozen? => false数组(Array)
数组是一个包含许多元素的对象 。这些元素可以是变量(例如 字符串 ,数字 ,哈希等) ,甚至可以是其他对象(包括构成多维数组的其他数组) 。定义中索引指的是数组元素中的一个序号 ,它从0开始 ,每个索引对应一个元素。说白了 ,就是一个内部元素内存地址连续的线性结构 。
声明数组:
A = []创建字符串数组:
> %w{ cat dog monkey } => ["cat", "dog", "monkey"]创建符号数组:
> %i{ cat dog monkey } => [:cat, :dog, :monkey]判断数组是否为空:
# 定义一个空数组 > days_of_week = [] => [] days_of_week.empty? => true也可以使用length或者size:
> days_of_week.length == 0 => true > days_of_week.size == 0 => true通过索引访问数组元素:
# 定义一个数组 > days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ] => [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ] > days_of_week[0] => "Mon" > days_of_week[1] => "Tues"使用数组的first和last方法访问首个和末尾元素:
> days_of_week.first => "Mon" > days_of_week.last => "Sun"通过index返回元素下标:
# 定义一个数组 > days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ] => [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ] > days_of_week.index("Wed") => 2提取子元素:
# 定义一个数组 > days_of_week = [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ] => [ "Mon", "Tues", "Wed", "Thu", "Fri", "Sat", "Sun" ] > days_of_week[1, 3] => ["Tues", "Wed", "Thu"]也可以针对数组指定范围:
> days_of_week[1..3] => ["Tues", "Wed", "Thu"]合并数组:
days1 = ["Mon", "Tue", "Wed"] days2 = ["Thu", "Fri", "Sat", "Sun"] days = days1 + days2 => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]使用<<将元素动态附加到现有数组:
days1 = ["Mon", "Tue", "Wed"] days1 << "Thu" << "Fri" << "Sat" << "Sun" => ["Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"]数组的交集 &:
operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"] linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"] operating_systems & linux_systems => ["Fedora", "SuSE", "RHEL"]数组的差集 -
operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"] linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"] operating_systems - linux_systems linux_systems - operating_systems数组的并集 |
operating_systems = ["Fedora", "SuSE", "RHEL", "Windows", "MacOS"] linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"] operating_systems | linux_systems => ["Fedora", "SuSE", "RHEL", "Windows", "MacOS", "PCLinuxOS", "Ubuntu"]数组删除重复元素:
linux_systems = ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora", "RHEL", "SuSE"] linux_systems.uniq => ["RHEL", "SuSE", "PCLinuxOS", "Ubuntu", "Fedora"]向数组中增加或减少元素(push和pop)
colors = ["red", "green", "blue"] => ["red", "green", "blue"] colors.push "indigo" => ["red", "green", "blue", "indigo"] colors.push "violet" => ["red", "green", "blue", "indigo", "violet"] colors.pop => "violet" colors.pop => "indigo"基于先进后出原则 。
数组插入元素:
colors = ["red", "green", "blue"] => ["red", "green", "blue"] colors.insert( 1, "orange" ) => ["red", "orange", "green", "blue"]基于下标来删除元素:
colors = ["red", "green", "blue"] => ["red", "green", "blue"] colors.delete_at(1) => "green" colors => ["red", "blue"]基于元素内容来删除:
colors = ["red", "green", "blue"] => ["red", "green", "blue"] colors.delete("red") => "red" colors => ["green", "blue"]最后是排序:
numbers = [1, 4, 6, 7, 3, 2, 5] => [1, 4, 6, 7, 3, 2, 5] numbers.sort => [1, 2, 3, 4, 5, 6, 7]布尔和Nil
true 和 false 为两个布尔型的值 ,与其他语言理解有差别的是 ,除了 false 和 nil 外 ,其他值都为 true:
!true # false !false # true !nil # true !0 # false ![] # falsenil 表示空值对象。对于值判空操作可调用 nil? 方法:
false.nil? # false nil.nil? # true需要注意的是,Ruby3中的nil是一个对象 ,表示没有任何东西的对象 ,而不是没有对象 。nil与nil的比较无论是==还是eql?都返回true 。
结语
字符 、数字 、布尔是不可变对象,而字符串 、数组 、哈希是可变对象 ,Ruby3中所有不可变对象的多个同值对象 ,都会指向同一个对象的内存地址 。例如所有的1数值都是同一个对象 ,所有的nil 、布尔值相同的字符对象也都是指向同一个对象 ,这也导致了Ruby3中不支持++或者--这样的操作 ,因为这要求在内存地址中指向的原对象进行增减操作 ,造成对象引用混乱的现象 。
创心域SEO版权声明:以上内容作者已申请原创保护,未经允许不得转载,侵权必究!授权事宜、对本内容有异议或投诉,敬请联系网站管理员,我们将尽快回复您,谢谢合作!