[ruby] Ruby基础

309 阅读6分钟

Ruby是一门动态、开源的语言,专注简洁和生产力,拥有非常强大的面向对象的设计(但依然可以使用Ruby编写函数式风格的程序)。

作为一门通用的语言,Ruby可用于Web开发、shell脚本编写、文本解析和包管理等领域。

Everything in Ruby is an object.

在Ruby中,不管是方法调用,还是条件判断,括号()通常是可选的。

命名规则

变量命名采用snake_case,类命名采用CamelCase。

first_name = "Michael", last_name = "Hart1"

String 类。

条件判断

简答的条件判断使用if end,如: 

password = "foo"
if password.length < 6
  puts "Password is too short"
else
  puts "Password is too long"
end

多分支条件判断使用 if elsif else end

password = "foo"
if password.length < 6
  puts "Password is too short"
elsif password.length < 50
  puts "Password is just right!"
else
  puts "Password is too long"
end

如果条件判断的代码块只有一行语句,那么if判断可以放在语句末尾,如:

"Password is too short" if password.length < 6。这种情况也可以使用unless,表示对if的含义取反,上面的例句可以表示为:"Password is too short" unless password.length >= 6

循环(for)

Ruby中循环会与Range结合使用。同时,Ruby还提供了若干方法,可以替代循环,如:

  1. times 定义在Integer类上的方法,控制代码块执行的次数。可以替代循环,如:5.times {|i| puts i} 输出 0 1 2 3 4。
  2. upto 定义在Integer, String, Date上的方法,也可以作为循环的替代实现,如:1.upto(5) {|i| puts i} 输出1 2 3 4 5。
  3. downto 与upto类似,不过从一个值开始,向下计数,如: 5.downto(1) {|i| puts i} 输出5 4 3 2 1。

方法

实际上,Ruby不会对对象属性或者方法做本质的区分,即你可以认为length是字符串的属性,也可以理解为是它的方法。

布尔方法

布尔方法表示返回true或false的方法。Ruby允许在方法名的末尾添加标点符号,尤其是问号(?),用来表示当前方法是布尔方法,如:"badger".empty? 返回 false。

基础类型

布尔值

Ruby支持常见的&&,||, !的布尔值操作符号。在布尔环境下,任何Ruby对象都有一个非true即false的布尔值,可以通过!!符号获取任何Ruby对象的布尔值,如:!!"foo"返回true。

在布尔环境下,只有false或nill才是false,其他任何值都认为是true("",0代表true)。

Range

表示范围,如 0..4。通常与循环结合使用,如:

for i in 0..4
  puts i
end # 输出0 1 2 3 4

常用的Range方法:

  1. to_a 将Range转换为数组,如:(0..3).to_a 返回 [0, 1, 2, 3]

String

拼接与插值

拼接:使用加号(+)完成字符串拼接,如 first_name + " " + last_name 返回 "Michael Hart1"

插值:使用#{..}完成字符串的插值,如"#{first_name} is my first name." 返回 "Michael is my first name"

单引号/双引号字符串

二者显著的区别在于单引号字符串会原样输出所包含的内容,如 '#{first_name}'会输出 #{first_name}而不是 "Michael"。

常用的String属性/方法:

  1. length 表示字符长的长度,如:"hello".length 返回5。
  2. empty? 判断字符串是否为空串,如:"".empty? 返回true。 
  3. downcase 将字符串转换为小写,如:"ABC".downcase 返回abc。
  4. upcase 将字符串转换为大小,如:"abc".upcase 返回ABC。
  5. include? 判断字符串是否包含某个子串,如:"hello".include? "lo",返回true。
  6. index 查找子串首次出现的下标,找不到返回nil,如:"hello".index "el",返回1。"hello".index "xx" 返回nil。
  7. split 将字符串转换为数组,用分隔符切分字符串,如 "a b c".split(" "),返回["a", "b", "c"]
  8. chars 返回字符串的字符数组,如:"abc".chars 返回["a", "b", "c"]。

通过下标索引返回的是包含单个字符的子串,如 "hello"[0]返回"h"。

Array

Ruby中的数组可以包含任何类型,如 a = [1, "hello", true]是合法的Ruby数组定义。

数组通过下标方法元素,如a[0]返回1。如果下标大于等于数组长度,通过下标方法数组元素将返回nil。

Ruby中数组支持负数下标,表示从后向前访问数组元素,如:a[-1]返回true。访问最后一个元素用-1。

常用的数组方法:

  1. last 获取数组的最后一个元素,如:a.last 返回true。
  2. slice 获取数组分片,方法既支持传入起始index,及分片的元素个数;也支持传入Range,表示分片的元素范围。如:a.slice 1, 2 返回 ["hello", true],a.slice 1..2 返回 ["hello", true]。
  3. length 返回数组的长度,如:a.length 返回3。
  4. include? 判断数组是否包含元素,如:a.include? false 返回 false。
  5. sort 按数字大小排序数组元素,排序后数组会作为方法的结果返回,原数组不会改变。
  6. sort! 同sort方法,但是会改变原数组。
  7. reverse 将数组反转。reverse!同reverse,但是会改变原数组。
  8. push 向数组末尾添加元素,会改变原数组。
  9. pop 从数组末尾删除元素,会改变原数组。
  10. join 将数组元素拼接,组合成字符创,如:a.join("--") 返回 "1--hello--true"。

通常,一个Ruby方法如果以感叹号(!)结尾,表示它的行为会直接作用于当前变量,如Array#sort!方法会改变数组元素的排序,而Array#sort方法会将排序后的数组返回,不会更改原数组。

可以通过 << (shovel符号) 向数组末尾添加元素,如:a << "a"<<"b" 返回 [1, "hello", true, "a", "b"]。

数组遍历

有2种方法可以遍历数组:

  1. 通过for循环, 如:for i in 0..(a.length-1) do puts a[i] end 输出 1 "hello" true。
  2. 通过each方法, 如:a.each do |i| puts i end 输出  1 "hello" true。

数学运算

Ruby支持基础的 + - * / 。

其中除法(/)是整数除法,如:10/4 返回2,如果要返回浮点数,需要将其中一个换成浮点数,如10/4.0 返回2.5。

其他复杂的数学运算通过Math模块提供,如:Math::PI,Math.sqrt,Math.cos,Math.log,Math.log10等。

指数运算

通过**实现,如 2 ** 3 返回 8

to_s可以将数字转换为字符串,如:6.to_s 返回 "6"。

to_i可以将数组字符串转换为整数,如:"6".to_i  返回6。

to_f 可以将浮点字符串转换为浮点数,如:"1.2".to_f 返回1.2。

时间

Array.new返回空数组。String.new返回空串。

Time.new 返回当前时间,如:

now = Time.new # 返回 2023-01-07 17:46:31 +0800
now.year # 返回年 2023
now.month # 返回月 1
now.day # 返回日 7
now.wday # 返回当前周中的第几天。Ruby中沿用美国标准:周日为一周的第一天,0-indexed。
now.hour # 返回 17
now.min # 返回46
now.sec # 返回31

也可以提供参数给new方法,如:Time.new(2000, 1, 1, 1, 1, 12),返回2000-01-01 01:01:12 +0800。

Time.new使用当前时区,可以调用utc方法,转换成UTC时间,如:Time.new(2000, 1, 1, 1, 1, 12).utc 返回 1999-12-31 17:01:12 UTC。

Time实例可以通过减法操作获得相差的秒数。

Content mainly excerpted from 「Learn enough Ruby to be dangerous: publish gems and develop sinatra web apps with Ruby」by Michael Hartl