红袖添香,绝代妖娆,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
=> Numeric
31位以内的整数为 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
![] # false
nil 表明空值目标。关于值判空操作可调用 nil? 办法:
false.nil? # false
nil.nil? # true
需求留意的是,Ruby3中的nil是一个目标,表明没有任何东西的目标,而不是没有目标。nil与nil的比较无论是==仍是eql?都回来true。
结语
字符、数字、布尔是不可变目标,而字符串、数组、哈希是可变目标,Ruby3中一切不可变目标的多个同值目标,都会指向同一个目标的内存地址。例如一切的1数值都是同一个目标,一切的nil、布尔值相同的字符目标也都是指向同一个目标,这也导致了Ruby3中不支撑++或许--这样的操作,由于这要求在内存地址中指向的原目标进行增减操作,形成目标引证紊乱的现象。