# Debian, Ubuntu
$ sudo apt-get install ruby-full
# Windows
$ winget install RubyInstallerTeam.Ruby
$ brew install ruby # macOS
$ docker run -it --rm ruby:latest # Docker
# Specify gem in the Gemfile in the project root directory
ruby '3.1.2'
source 'https://rubygems.org'
gem 'nokogiri'
gem 'rack', '~>3.0.10'
gem 'rspec', :require => 'spec'
Install all gems in Gemfile
$ bundle install
Solve the problem of Gemfile.lock inconsistency between mac for development and linux for production
bundle lock --add-platform x86_64-linux
$ gem install bundler -v 2.4.20
$ gem install minitest -v 5.22.3
# Updating a single gem using Bundler
$ bundle update nokogiri
# Use Bundler to update each gem in the Gemfile
$ bundle update
# This is a single line comments.
=begin
Multi-line
Comment
=end
puts "Hello world!" # Inline comments for code
| Reserved words | Description |
|---|---|
__ENCODING__ |
The script encoding of the current file |
__LINE__ |
The line number of this keyword in the current file |
__FILE__ |
The path of the current file |
BEGIN |
Code enclosed in { } is run before the program is run |
END |
Code enclosed in { } is run at the end of the program |
alias |
Create an alias for an existing method, operator, or global variable |
and |
Logical AND operator |
begin |
Begin a block of code |
break |
Terminate a loop |
case |
Compare an expression with matching when clauses, terminated with end |
class |
Define a class |
def |
define a function/method |
defined? |
Check if a variable or function exist |
do |
Start a block of code, terminated with the end keyword |
else |
Execute the following code if previous conditions are not met |
elsif |
Alternative condition for if expressions |
end |
End blocks of code starting with keywords like begin, class,def,do,if, etc. |
ensure |
Always execute at the end of a block |
false |
Logical boolean value false |
for |
Start a for loop |
if |
Execute the code block if the condition is true |
in |
Used with for loop |
module |
Define a module |
next |
jump to the point before the evaluation of the loop condition |
nil |
Stand for null, invalid, or always false |
not |
Logical NOT operator |
or |
Logical OR operator |
redo |
Jump back to the loop condition evaluation |
rescue |
Evaluate expressions after an exception is raised |
retry |
Repeat method calls when called outside rescue, jump to the top of the block when called inside rescue |
return |
Return a value from a method or block |
self |
Refer to the current object |
super |
Call the same-named method in the superclass |
then |
Used as a separator withif,unless,when,case,rescue |
true |
Logical boolean value true |
undef |
Undefine methods/functions within the current class |
until |
Execute the code block until the condition is false |
when |
Begin a clause under a case statement |
while |
Execute the code block while the condition is true |
yield |
Execute the code block passed to a method |
andornot&&||!&|^~<<>>+-*/%**==!=><>=<=<=>===eql?equal?# Addition
1 + 1 #=> 2
# Subtraction
2 - 1 #=> 1
# Multiplication
2 * 2 #=> 4
# Division
10 / 5 #=> 2
17 / 5 #=> 3, not 3.4
17 / 5.0 #=> 3.4
# Exponentiation
2 ** 2 #=> 4
3 ** 4 #=> 81
# Modulus (remainder of division)
8 % 2 #=> 0 (8 / 2 = 4; no remainder)
10 % 4 #=> 2 (10 / 4 = 2 remainder 2)
a = 10
b = 20
a == b #=> false
a != b #=> true
a > b #=> false
a < b #=> true
a >= b #=> false
a <= b #=> true
# Comparison operators
a <=> b #=> -1
c = 20
c <=> b #=> 0
c <=> a #=> 1
# Equality used in when clauses for case statements
(1...10) === 5 #=> true
# True if the receiver and the argument have the same type and equal values
1.eql?(1.0) #=> false
c = a + b #=> 30
c += a #=> 40
c -= a #=> 30
c *= a #=> 300
c /= a #=> 30
c %= a #=> 3
c **= a #=> 59049
# Ruby parallel assignment
a = 10
b = 20
c = 30
a, b, c = 10, 20, 30
# Ruby bitwise operators
a = 60
b = 13
# & Binary AND operator copies a bit to the result if it exists in both operands.
a & b #=> 12
# | Binary OR operator copies a bit if it exists in either operand.
a | b #=> 61
# ^ Binary XOR operator copies a bit if it is set in one operand but not both.
a ^ b #=> 49
# ~ Binary Ones Complement is unary and has the effect of 'flipping' bits.
~a
# << Binary Left Shift Operator. The left operand's value is moved
# left by the number of bits specified by the right operand.
a << 2
# >> Binary Right Shift Operator. The left operand's value is moved
# right by the number of bits specified by the right operand.
a >> 2
# Ruby logical operators
a and b #=> true.
a or b #=> true.
a && b #=> true.
(a || b) #=> true.
!(a && b) #=> false.
not(a && b) #=> false.
# Ruby ternary operator
# ? :
# If condition is true ? Then value X : Otherwise value Y
a == 10 ? puts 'Right' : puts 'Wrong'
# Ruby range operators
# .. Creates a range from the start point to the end point (inclusive)
1..10 #=> Creates a range from 1 to 10 (inclusive of 1 and 10)
# ... Creates an exclusive range from the start point to the end point
1...10 #=> Creates an exclusive range from 1 to 10
From highest to lowest, this is the precedence table for ruby. High precedence operations happen before low precedence operations.
, >=, <, <=
| - | - | - | - |
|---|---|---|---|
| Name | Scope | Example | Explanation |
[a-z] or _ |
Local | count = 10 or _count = 10 |
Local variables must be initialized |
@ |
Instance variable | @id = [] |
Instance variables have a "nil" value before initialization |
@@ |
Class variable | @@name = [] |
Class variables must be initialized |
$ |
Global variable | $version = "0.8.9" |
Global variables have a "nil" value before initialization |
[A-Z] |
Constant | PI = 3.14 |
Constant variables must be initialized, you can change constants, but you will receive a warning |
There are five different types of variables. The first character determines the range To read in deap about variables check User Guide cap 19,20,21,22,23 Pre-Defined Variables and Constants
defined? count
"local-variable"
defined? @id
"instance-variable"
defined? @@name
"class variable"
defined? $version
"global-variable"
defined? PI
"constant"
| - | - | - | - |
|---|---|---|---|
| Type | Example | Class | Documentation |
Integer |
a = 17 | a.class > Integer a.class.superclass > Numeric |
# |
Float |
a = 87.23 | a.class > Float a.class.superclass > Numeric |
# |
String |
a = "Hello universe" | a.class > String | # |
Array |
a = [12, 34] | a.class > Array | # |
Hash |
a = | a.class > Hash | # |
Boolean |
a = false a = true |
a.class > FalseClass a.class > TrueClass |
TrueClass FalseClass |
Symbol |
a = :status | a.class > Symbol | # |
Range |
a = 1..3 | a.class > Range | # |
Nil |
a = nil | a.class > NilClass | # |
# Both are synonyms
a = 37
a.kind_of? Integer
# true
a.is_a? Integer
# true
week_days = {sunday: 11, monday: 222}
2.even?
# true
3.even?
# false
.. Used to create inclusive ranges
range = 1..10
range.to_a
# output => [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
... Used to create exclusive ranges
range = 1...10
range.to_a
# output => [1, 2, 3, 4, 5, 6, 7, 8, 9]
some useful methods
| Method name | Output |
|---|---|
cover? |
(1..5).cover?(5) => true |
end |
('a'..'z').end => "z" |
first |
(1..5).first => 1 |
first(3) |
('A'..'Z').first(2) => ["A", "B"] |
eql? |
((0..2).eql?(0..5) => false |
step in Range(1..20).step(2) { |number| puts "#{number}"}
# output
# 1
# 3
# 5
# 7
# 9
# 11
# 13
# 15
# 17
# 19
num = 2
puts 'two' if num == 2
If the condition is true, execute the code
temp = 19
if temp >= 25
puts "hot"
elsif temp < 25 && temp >= 18
puts "normal"
else
puts "cold"
end
# output => normal
# Unless contrary to if , evaluates when the statement is false
name = "rob"
# if name != "bob"
unless name == "bob"
puts "hello stranger"
else
puts "hello bob"
end
# output => hello stranger
num = 6
puts 'not two' unless num == 2
# output => not two
# case returns the value of the last expression executed
case input
# Check for an integer, 19
when 19
puts "It's 19"
# Check for an exact string,“Zaman”
when "Zaman"
puts "Hi Zaman"
when 7..11
puts "It's between 7 and 11"
# Check multiple values, "coffee"
when "tea", "coffee"
puts "Happy days"
end
case input
when 19 then puts "It's 19"
end
case input
when 19 then puts "It's 19"
else
puts "It's not 19"
end
marks = 86
result = case marks
when 0..49 then "Fail"
when 50..64 then "Pass"
when 65..74 then "Credit"
when 75..84 then "Distinction"
when 85..100 then "High Distinction"
else "Invalid marks"
end
puts result
# High Distinction
name = "World"
puts "Hello #{name}"
puts "The total is #{1+1}"
# "the total is 2"
String interpolation allows you to combine strings together
string = "abc123"
string[0,3]
# "abc"
string[3,3]
# "123"
string[0..-2]
# "abc12"
#remove or replace the substring
string[0..2] = ""
puts string
# "123"
A substring is a small part of a string, which is useful if you only want that specific part, like the beginning, middle, or end
"HELLO World".downcase # "hello world"
"hello worlD".upcase # "HELLO WORLD"
"hEllo wOrlD".capitalize # "Hello world"
"hEllo WOrlD".swapcase # "HeLLO woRLd"
| Function Name | Output | Note |
|---|---|---|
| length or size | "HELLO World".length => 11 "HELLO World".size => 11 |
Returns the length of the string |
| reverse | "hello worlD".reverse => "Dlrow olleh" |
Returns the reversed string |
| include? other_str | "hEllo wOrlD".include? "w" => true |
Returns true if the string or character exists, otherwise returns false |
| gsub(pattern, replacement) | "hEllo wOrlD".gsub(" ", "_") => "hEllo_wOrlD" |
gsub or global substitute replaces one or more strings with the provided string |
| gsub(pattern, hash) | "organization".gsub("z", 'z' => 's') => "organisation" |
gsub or global substitute replaces one or more strings with the provided hash |
| gsub(pattern) | "Price of the phone is 1000 AUD".gsub(/\d+/) {\| s\| '$'+s }"Price of the phone is $1000 AUD" |
gsub or global substitute replaces one or more strings with the provided block |
| strip | " hEllo WOrlD ".strip "hEllo WOrlD" |
It will remove (trim) any leading and trailing characters: null (“\x00”), horizontal tab (“\t”), newline (\n), vertical tab (“\v”), form feed (f), carriage return(\r), space (" ") |
| prepend | a = "world" <br> a.prepend("hello ") "hello world" |
Adds the string before another string |
| insert | a = "hello" <br> a.insert(a.length, " world") "hello world" |
Inserts the string at a specific position |
| start_with? | string = "ruby programming" string.start_with? "ruby" true |
Checks if the string starts with a specific prefix |
| end_with? | string = "ruby programming" string.end_with? "ruby" false |
Checks if the string ends with a specific prefix |
| delete_suffix | string = "sausage is expensive" string.delete_suffix(" is expensive") "sausage" |
Deletes the suffix from the string |
| delete_prefix | string = "sausage is expensive" string.delete_prefix("sausage") " is expensive" |
Deletes the prefix from the string |
| split | string = "a b c d" <br> string.split ["a", "b", "c", "d"] |
Converts the string into an array of characters |
| join | arr = ['a', 'b', 'c'] <br> arr.join => "abc" |
Converts an array into a string |
| to_i | a = "49" <br> a.to_i => 49 |
Converts the string into an integer |
| chop | "abcd?".chop("?") => "abcd" |
Deletes the last character from the string |
| count | str = "aaab" <br> str.count("a") 3 |
Counts the characters in the string |
| to_f | a = "49" a.to_f 49.0 |
Converts the string into a floating point number |
| to_sym | a = "key" a.to_sym :key |
Converts the string into a symbol |
| match | "abcd?".match(/ab/) => #<MatchData "ab"> |
Converts the pattern into a regular expression and calls its match method on the string |
| empty? | "hello".empty? => false |
Returns true if the length of the string is zero |
| squeeze | "Booook".squeeze => "Bok" |
Returns a copy of the string where runs of the same character are replaced by a single character |
| * | puts "Ruby " * 4 => Ruby Ruby Ruby Ruby |
Returns the concatenation of multiple copies of self |
| + | "sammy " + "shark" => "sammyshark" |
Returns the concatenation of self and the given other string |
| eql? | s = 'foo' => true s.eql?('foo') => true |
Returns true if the objects have the same length and content; false otherwise |
def method_name(parameter1, parameter2)
puts "#{parameter1} #{parameter2}"
parameter1 + parameter2
end
res = method_name(20, 10)
# output => 30
def method_name(parameter1, parameter2)
puts "#{parameter1} #{parameter2}"
return parameter1 + parameter2
end
# output => 30
res = method_name(20, 10)
# output => 30
def method_name(parameter1, parameter2)
puts "#{parameter1} #{parameter2}"
return parameter1 + parameter2
end
# output => 30
res = method_name(parameter1, parameter2)
# Methods can be called without parentheses
res = method_name parameter1, parameter2
类方法是类级别的方法,有多种定义方式
class Mobile
def self.ring
"ring ring ring..."
end
end
Mobile.ring
class Mobile
def Mobile.ring
"ring ring ring..."
end
end
Mobile.ring
class Mobile
class << self
def ring
"ring ring ring..."
end
end
end
Mobile.ring
类方法是类对象的实例方法。创建新类时,会初始化一个 "Class" 类型对象 并赋给全局常量(本例为 Mobile)
Mobile = Class.new do
def self.ring
"ring ring ring..."
end
end
Mobile.ring
Mobile = Class.new
class << Mobile
def ring
"ring ring ring..."
end
end
Mobile.ring
def method_name(num1, num2 = num1)
return num1 + num2
end
res = method_name(10)
# output => 20
def method_name(parameter1, parameter2, type = "ADD")
puts "#{parameter1} #{parameter2}"
return parameter1 + parameter2 if type == "ADD"
return parameter1 - parameter2 if type == "SUB"
end
res = method_name(20, 10)
# output => 30
def method_name(type, *values)
return values.reduce(:+) if type == "ADD"
return values.reduce(:-) if type == "SUB"
end
numbers = [2, 2, 2, 3, 3, 3]
res = method_name("ADD", *numbers)
# output => 15
res = method_name("SUB", *numbers)
# output => -11
# Or you can provide a value like this
res = method_name("ADD", 2, 2, 2, 3, 3, 3)
# output => 15
a = ["Drama", "Mystery", "Crime",
"Sci-fi", "Disaster", "Thriller"]
a.sort
puts a
# We did not modify the object
# Drama
# Mystery
# Crime
# Sci-fi
# Disaster
# Thriller
a.sort!
puts a
# Modify object
# Crime
# Disaster
# Drama
# Mystery
# Sci-fi
# Thriller
若要修改对象本身,在方法后加 !
在 Ruby 中,以问号 (?) 结尾的方法称为布尔方法,返回 true 或 false
"some text".nil?
# false
nil.nil?
# true
你也可以自定义布尔方法
def is_vowel?(char)
['a','e','i','o','u'].include? char
end
is_vowel? 'a'
# true
is_vowel? 'b'
# false
# return value
def give_me_data
data = yield
puts "data = #{data}"
end
give_me_data { "Big data" }
# output => data = Big data
do…end(多行)或花括号 {…}(单行)之间的代码称为代码块,
并可在两根竖线之间定义多个参数 ( |arg1, arg2|)
salary = [399, 234, 566, 533, 233]
salary.each { |s| puts s }
# puts s = block body
# |s| = block arguments
salary.each do |s|
a = 10
res = a * s
puts res
end
# Block
# a = 10
# res = a * s
# puts res
# block parameters
# |s|
代码块可作为方法参数传入或与方法调用关联;代码块返回最后求值的语句
def give_me_data
puts "I am inside give_me_data method"
yield
puts "I am back in give_me_data method"
end
give_me_data { puts "Big data" }
# output
# I am inside give_me_data method
# Big data
# I am back in give_me_data method
def give_me_data
yield
yield
yield
end
give_me_data { puts "Big data" }
# output
# Big data
# Big data
# Big data
def give_me_data
yield 10
yield 100
yield 30
end
give_me_data { |data| puts "Big data #{data} TB" }
# output
# Big data 10 TB
# Big data 100 TB
# Big data 30 TB
def give_me_data
yield "Big data", 10, "TB"
yield "Big data", 100, "GB"
yield "Big data", 30, "MB"
end
give_me_data { |text, data, unit| puts "#{text} #{data} #{unit}" }
# output
# Big data 10 TB
# Big data 100 GB
# Big data 30 MB
give_me_data
puts "I'm inside the give_me_data method"
end
def test
puts "I'm inside the test method"
give_me_data { return 10 } # Code returns from here
puts "I am back in test method"
end
return_value = test
# output
# I'm inside the test method
# I'm inside the give_me_data method
# 10
def give_me_data(&block)
block.call
block.call
end
give_me_data { puts "Big data" }
# output
# Big data
# Big data
def give_me_data
yield
end
give_me_data
# output
# LocalJumpError: no block given (yield)
def give_me_data
return "no block" unless block_given?
yield
end
give_me_data { puts "Big data" }
give_me_data
# output
# Big data
p = Proc.new { puts "Hello World" }
def give_me_data(proc)
proc.call
end
give_me_data p
# output
# Hello World
proc 类似可存入变量的代码块
p = Proc.new { |count| "Hello World " * count }
def give_me_data(proc)
proc.call 5, 2
end
give_me_data p
# output
# ""
p = Proc.new { return 10 }
p.call
# output
LocalJumpError: unexpected return
def give_me_data
puts "I'm inside the give_me_data method"
p = Proc.new { return 10 }
p.call # Code returns from here
puts "I am back in give_me_data method"
end
return_value = give_me_data
puts return_value
# output
# I'm inside the give_me_data method
# 10
l = lambda { puts "Hello World" }
# shorthand
l = -> { puts "Hello World" }
# transfer lambda
l.call
# output => Hello World
调用 lambda 有多种方式
l.()
l[]
l = -> (count) { "Hello World " * count }
l.call 5
# output
# ""
l.call 5, 2
# output
wrong number of arguments (given 2, expected 1)
def give_me_data
puts "I am inside give_me_data method"
l = -> { return 10 }
l.call
puts "I am back in give_me_data method"
end
return_value = give_me_data
puts return_value
# output
# I am inside give_me_data method
# I am back in give_me_data method
# nil # because puts return nil
l = -> { return 10 }
l.call
# output => 10
array = Array.new #=> []
# or
array = []
array = [1, "two", 3.0]
#=> [1, "two", 3.0]
numbers = Array.new(3)
#=> [nil, nil, nil]
numbers = Array.new(3, 7)
#=> [7, 7, 7]
numbers = Array.new(3, true)
#=> [true, true, true]
numbers = []
numbers.fill(7, 0..2) #=> [7, 7, 7]
array_with_hashes = Array.new(2) { {} } #=> [{}, {}]
array_with_hashes[0][:name] = "Bob"
array_with_hashes[0][:id] = 10 #=> [{:name=>"Bob", :id=>10}, {}]
temperature_data = [
["A908", 38],
["A909", 37],
["A910", 38],
]
temperature_data[0] #=> ["A908", 38]
temperature_data[0][0] #=> "A908"
temperature_data[0][1] #=> 38
str_array = [
"This", "is", "a", "small", "array"
]
str_array[0] #=> "This"
str_array[1] #=> "is"
str_array[4] #=> "array"
str_array = [
"This", "is", "a", "small", "array"
]
# Index -1 represents the last element
str_array[-1] #=> "array"
# Index -2 represents the second to last element
str_array[-2] #=> "small"
str_array[-6] #=> nil
str_array = [
"This", "is", "a", "small", "array"
]
puts str_array.at(0) #=> "This"
arr = [1, 2, 3, 4, 5, 6]
arr[100] #=> nil
arr[-3] #=> 4
arr[2, 3] #=> [3, 4, 5]
arr[1..4] #=> [2, 3, 4, 5]
arr[1..-3] #=> [2, 3, 4]
arr = ['a', 'b', 'c', 'd', 'e', 'f']
arr.fetch(100)
#=> IndexError: Index outside array bounds 100:-6...6
arr.fetch(100, "oops") #=> "oops"
越界时给出默认值
arr = [1, 2, 3, 4, 5, 6]
arr.first # first value => 1
arr.last # last value => 6
# take Returns the first n elements
arr.take(3) #=> [1, 2, 3]
# drop after n elements have been deleted
arr.drop(3) #=> [4, 5, 6]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.push(11)
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
numbers.push(12, 13, 14)
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
num_array = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
num_array.pop #=> 10
num_array
#=> [1, 2, 3, 4, 5, 6, 7, 8, 9]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.unshift(0)
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.unshift(-3, -2, -1)
#=> [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.shift #=> 1
numbers
#=> [2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.delete_at(2) #=> 4
numbers
#=> [2, 3, 5, 6, 7, 8, 9, 10]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.delete(2) #=> 2
numbers #=> [3, 5, 6, 7, 8, 9, 10]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.insert(0, 0)
#=> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.insert(0, -3, -2, -1)
#=> [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.insert(-1, 12, 13, 14)
#=> [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 14]
numbers.insert(-4, 11)
#=> [-3, -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14]
numbers = Array.new(10) { |n| n = n * 2 }
#=> [0, 2, 4, 6, 8, 10, 12, 14, 16, 18]
numbers = Array(100..110)
#=> [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
# Or we can convert the range to an array
(100..110).to_a
#=> [100, 101, 102, 103, 104, 105, 106, 107, 108, 109, 110]
arr = ['foo', 0, nil, 'bar', 7, nil]
arr.compact #=> ['foo', 0, 'bar', 7]
arr #=> ['foo', 0, nil, 'bar', 7, nil]
arr.compact! #=> ['foo', 0, 'bar', 7]
arr #=> ['foo', 0, 'bar', 7]
arr = [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
arr.uniq #=> [2, 5, 6, 556, 8, 9, 0, 123]
arr # => [2, 5, 6, 556, 6, 6, 8, 9, 0, 123, 556]
arr.uniq! #=> [2, 5, 6, 556, 8, 9, 0, 123]
arr #=> [2, 5, 6, 556, 8, 9, 0, 123]
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
planets.include? "Mars"
# output => true
planets.include? "Pluto"
# output => false
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
planets.size
# output => 8
planets.length
# output => 8
可用 size 或 length,二者同义
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.clear
# output => []
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers[0]
# or
numbers.first
# output => 1
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers[-1]
# or
numbers.last
# output => 10
a = ["tom", "mot", "otm"]
b = [2, 3, 5]
a.zip(b)
# output
# [["tom", 2], ["mot", 3], ["otm", 5]]
primes = [7, 2, 3, 5]
sorted_primes = primes.sort
puts "#{sorted_primes}"
# output => [2, 3, 5, 7]
或就地排序
primes = [7, 2, 3, 5]
primes.sort!
puts "#{primes}"
# output => [2, 3, 5, 7]
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
planets.sort
# output
# ["Earth", "Jupiter", "Mars", "Mercury", "Neptune", "Saturn", "Uranus", "Venus"]
planets.sort_by { |p| p }
# output
# ["Earth", "Jupiter", "Mars", "Mercury", "Neptune", "Saturn", "Uranus", "Venus"]
planets.sort_by { |p| p.length }
# output
# ["Mars", "Earth", "Venus", "Saturn", "Uranus", "Neptune", "Jupiter", "Mercury"]
primes = [7, 2, 3, 5]
primes.max_by { |p| p }
# output => 7
# numbers[start..end], both index are inclusive
puts numbers[0..3]
# 1
# 2
# 3
# 4
# numbers[start..end], end index is exclusive
puts numbers[0...3]
# 1
# 2
# 3
# or numbers[start..length]
puts numbers[0, 1]
# 1
primes = [7, 2, 3, 5]
primes.take(3)
# [7, 2, 3]
primes = [7, 2, 3, 5]
primes.fetch(3)
# 5
# Fetch will throw an error if the element does not exist
primes.fetch(10)
# (index 10 outside of array bounds: -4...4)
# or get an 默认值
primes.fetch(10, -1)
# -1
primes = [7, 2, 3, 5]
primes.drop(3)
# [5]
primes = [7, 2, 3, 5]
primes.shift
# [2, 3, 5]
primes = [7, 2, 3, 5]
primes.pop
# [7, 2, 3]
primes = [7, 2, 3, 5]
primes.delete_at(-1)
# [7, 2, 3]
primes = [7, 2, 3, 5, 5]
primes.delete(5)
# [7, 2, 3]
# When you have single line blocks
salary = [399, 234, 566, 533, 233]
salary.each { |s| puts s }
# output
# 399
# 234
# 566
# 533
# 233
多行代码块可用 do 与 end 替代花括号 {}
salary.each do |s|
a = 10
res = a * s
puts res
end
# output
# 3990
# 2340
# 5660
# 5330
# 2330
也可用花括号 {},并以分号代替换行作为分隔
salary.each { |s| a = 10 ; res = a * s ; puts res }
salary = [399, 234, 566, 533, 233]
salary.each_with_index { |value, index| puts "#{index} #{value}" }
# output
# 0 399
# 1 234
# 2 566
# 3 533
# 4 233
salary = [399, 234, 566, 533, 233]
salary.each_index { |i| puts i}
# output
# 0
# 1
# 2
# 3
# 4
salary = [399, 234, 566, 533, 233]
salary.map { |s| s * 10 }
# return
# [3990, 2340, 5660, 5330, 2330]
# On the other hand, each returns the original value
salary = [399, 234, 566, 533, 233]
salary.each { |s| s * 10 }
# return
# [399, 234, 566, 533, 233]
salary = [399, 234, 566, 533, 233]
salary.collect { |s| s > 400 }
# output
# [false, false, true, true, false]
for value in [2, 3, 5, 7]
puts value
end
colors = [
{color: "red", count: 3}, {color: "red", count: 5}, {color: "black", count: 4}
]
colors.each_with_object(Hash.new(0)) { |color, hash| hash["color_"+color[:color]] = color[:color].upcase; hash["count_"+color[:color]] += color[:count] }
# output
{"color_red"=>"RED", "count_red"=>8, "color_black"=>"BLACK", "count_black"=>4}
[1, 2, 3].each_with_object(0) { |number, sum| sum += number}
# output
# 0
# Because 0 is immutable, and since the initial object is 0, the method returns 0
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
index = 0
while index < planets.size
puts "#{planets[index]}"
index += 1
end
a = 1
star = '*'
while a <= 10
puts star
star += '*'
a += 1
end
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
index = 0
loop do
puts "#{planets[index]}"
index += 1
break if planets[index] == "Mars" or index > planets.size
end
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
index = planets.size - 1
until index < 0
puts "#{planets[index]}"
index -= 1
end
a = 1
star = '*'
until star.length > 10
puts star
star += '*'
a += 1
end
10.times { puts "#{rand(1..100)}"}
# output
# will print 10 random numbers
虽然可以这样写,但不代表就应该这样遍历数组
data_sample = [2, 3, 5, 7]
data_sample.size.times { |index| puts "#{data_sample[index]}" }
# output
# 2
# 3
# 5
# 7
data_sample = [2, 3, 5, 7]
0.upto((data_sample.size - 1) / 2) { |index| puts "#{data_sample[index]}" }
# output
# 2
# 3
data_sample = [2, 3, 5, 7]
(data_sample.size - 1).downto(data_sample.size / 2) { |index| puts "#{data_sample[index]}" }
# output
# 7
# 5
1.step(20, 2) { |number| puts "#{number}"}
# output
# 1
# 3
# 5
# 7
# 9
# 11
# 13
# 15
# 17
# 19
19.step(1, -2) { |number| puts "#{number}"}
# output
# 19
# 17
# 15
# 13
# 11
# 9
# 7
# 5
# 3
# 1
numbers = [2, 2, 2, 2, 2]
numbers.inject{ |res, n| res + n }
# The output is the sum of all numbers
# If no initial value is set for res, the first element of the array is used as the initial value of res.
#10
# Now set the value of res to 11
numbers = [2, 2, 2, 2, 2]
numbers.inject(11) { |res, n| res + n }
# so 11 + 2, 13 + 2, 15 + 2, 17 + 2 and 19 + 2
# 21
# using symbol
numbers = [2, 2, 2, 2, 2]
numbers.inject(:+)
# output
# 10
使用初始值与符号
numbers = [2, 2, 2, 2, 2]
numbers.inject(11, :+)
# output
# 21
numbers = [2, 2, 2, 2, 2]
numbers.reduce(11, :+)
# output
# 21
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
planets.detect { |name| name.start_with?("E") and name.end_with?("h") }
# output
# Earth
salary = [399, 234, 566, 533, 233]
salary.detect { |s| s > 1000 }
# output
# nil
planets = ["Mercury", "Venus", "Earth", "Mars", "Jupiter", "Saturn", "Uranus", "Neptune"]
planets.find { |name| name.start_with?("E") and name.end_with?("h") }
# output
# Earth
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.select { |n| n % 2 == 0 }
# Now you have an even array
# [2, 4, 6, 8, 10]
# If there are no values that satisfy your logic, return an empty array
[1, 1, 1].select { |n| n % 2 == 0 }
# no even numbers
# []
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.reject { |n| n % 2 == 0 }
# Reject if the number is even, so now we have an odd array
# [1, 3, 5, 7, 9]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.keep_if { |n| n % 2 == 0 }
# numbers Array contains only even numbers
# [2, 4, 6, 8, 10]
numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]
numbers.delete_if { |n| n % 2 == 0 }
# numbers Array contains only odd numbers
# [1, 3, 5, 7, 9]
numbers = [1, 2, 3, 1, 2, 3, 0]
numbers.drop_while { |n| n < 3 }
# is 3 less than 3, returns false, so delete 1, 2
# [3, 1, 2, 3, 0]
words = %w[first second third fourth fifth sixth]
str = ""
words.reverse_each {|word| str += "#{word} "}
p str #=> "sixth fifth fourth third second first "
| 名称 | 使用场景 |
|---|---|
all? |
检查是否所有元素都满足条件 |
any? |
检查是否至少有一个元素满足条件 |
one? |
检查是否恰好有一个元素满足条件 |
none? |
检查是否没有任何元素满足条件(与 any? 相反) |
empty? |
检查对象是否为空 |
include? |
检查对象中是否存在某元素 |
[2, 4, 6, 8, 10].all? { |num| num % 2 == 0 }
# true
[1, 4, 6, 8, 10].all? { |num| num % 2 == 0 }
# false
[1, 3, 5, 7, 10].any? { |num| num % 2 == 0 }
# true
[1, 3, 5, 7, 19].any? { |num| num % 2 == 0 }
# false
[1, 3, 2, 5, 7].one? { |num| num % 2 == 0 }
# true
[1, 3, 2, 5, 4].one? { |num| num % 2 == 0 }
# false
[1, 3, 5, 7, 9].none? { |num| num % 2 == 0 }
# true
[2, 3, 5, 7, 9].none? { |num| num % 2 == 0 }
# false
[].empty?
# true
[1, 3, 5, 7, 9].empty?
# false
& 返回新数组,包含 array 与 other_array 的共有元素;去重;使用 eql?
来比较元素intersection 返回新数组,包含 self 与所有给定数组 other_arrays 的共有元素;重复项
会省略;使用 eql? 比较元素+ 返回包含 self 全部元素后接给定数组全部元素的新数组- 返回 self 中不在给定数组中的全部元素union 返回 self 与给定数组全部元素的并集(去重)difference 返回 self 中不在任何给定数组中的元素product 返回 self 与给定数组元素的全部组合(笛卡尔积)[0, 1, 2, 3] & [1, 2] # => [1, 2]
[0, 1, 0, 1] & [0, 1] # => [0, 1]
[0, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3])
# => [0, 1]
[0, 0, 1, 1, 2, 3].intersection([0, 1, 2], [0, 1, 3])
# => [0, 1]
a = [0, 1] + [2, 3]
a # => [0, 1, 2, 3]
[0, 1, 1, 2, 1, 1, 3, 1, 1] - [1]
# => [0, 2, 3]
[0, 1, 2, 3] - [3, 0]
# => [1, 2]
[0, 1, 2] - [4]
# => [0, 1, 2]
[0, 1, 2, 3].union([4, 5], [6, 7])
# => [0, 1, 2, 3, 4, 5, 6, 7]
[0, 1, 1].union([2, 1], [3, 1])
# => [0, 1, 2, 3]
[0, 1, 2, 3].union([3, 2], [1, 0])
# => [0, 1, 2, 3]
[0, 1, 1, 2, 1, 1, 3, 1, 1].difference([1])
# => [0, 2, 3]
[0, 1, 2, 3].difference([3, 0], [1, 3])
# => [2]
[0, 1, 2].difference([4])
# => [0, 1, 2]
a = [0, 1, 2]
a1 = [3, 4]
p = a.product(a1)
p.size # => 6 # a.size * a1.size
p # => [[0, 3], [0, 4], [1, 3], [1, 4], [2, 3], [2, 4]]
# variable count
count = 4
# using while loop
# here conditional is count i.e. 4
while count >= 1
# statements to be executed
puts "Ruby Cheatsheet"
count = count - 1
# while loop ends here
end
output
Ruby Cheatsheet
Ruby Cheatsheet
Ruby Cheatsheet
Ruby Cheatsheet
# loop using range as expression
text = "Ruby Cheatsheet"
# using for loop with the range
for count in 1..5 do
puts text
end
output
Ruby Cheatsheet
Ruby Cheatsheet
Ruby Cheatsheet
Ruby Cheatsheet
Ruby Cheatsheet
# starting of do..while loop
loop do
puts "Ruby Cheatsheet"
val = '7'
# using boolean expressions
if val == '7'
break
end
# ending of ruby do..while loop
end
output
Ruby Cheatsheet
var = 7
# here do is 可选
until var == 11 do
# code to be executed
puts var * 10
var = var + 1
# here loop ends
end
output
70
80
90
100
salary = [399, 234, 566, 533, 233]
salary.each do |s|
break if s == 566
puts s
end
# output
# 399
# 234
使用 break 关键字
salary = [399, 234, 566, 533, 233]
salary.each do |s|
next if s == 533
puts s
end
# output
# 399
# 234
# 566
# 233
使用 next 关键字
data = [456, 3000]
retry_count = 0
status = "network failure"
sum = 0
data.each do |d|
if retry_count == 3
status = "connection established"
retry_count = 0
redo
elsif status == "network failure" and retry_count < 5
puts "network failure #{retry_count}"
retry_count += 1
redo
elsif status == "connection established"
puts d
sum += d
end
end
# output of sum
# 3456
numbers = [2, 2, 44, 44]
sum = 0
begin
numbers.each do |s|
if rand(1..10) == 5
puts "hi 5, let's do it again!"
sum = 0
raise "hi 5"
end
puts s
sum += s
end
rescue
retry
end
class Person
# when you create a new object, it looks for a method named initialize and executes it, like a constructor in java
# def initialize(name, number)
#@name = name
#@number = number
# end
# instance variable
# @name
# class variable
# @@count
# attr_accessor acts as a getter and setter for the following instance attributes
attr_accessor :name, :number
# class variable must be initialized
@@count = 0
def self.count
@@count
end
def self.count=(count)
@@count = count
end
def initialize
@@count += 1
end
end
# create an instance of the Person class
p1 = Person.new
# set attributes of the Person class
p1.name = "Yukihiro Matsumoto"
p1.number = 9999999999
# get attributes of the Person class
puts "#{p1.name}"
puts "#{p1.number}"
puts "#{Person.count}"
# Yukihiro Matsumoto
#
# 1
p2 = Person.new
p2.name = "Yukihiro Matsumoto"
p2.number = 9999999999
# get attributes of the Person class
puts "#{p2.name}"
puts "#{p2.number}"
puts "#{Person.count}"
# Yukihiro Matsumoto
#
# 2
# set class variable
Person.count = 3
puts "#{Person.count}"
# 3
class Person
attr_accessor :name, :number
end
# Inherit methods and properties from parent class using < symbol
class Student < Person
attr_accessor :id
end
s = Student.new
s.name = "James Bond"
s.number = 700
s.id = 678
puts "#{p.name}"
James Bond
puts "#{p.number}"
700
puts "#{p.id}"
678
class Vehicle; end
class Car < Vehicle; end
class Audi < Car; end
car = Car.new
car.instance_of? Vehicle
false
car.instance_of? Car
true
car.instance_of? Audi
false
a = 7
a.instance_of? Integer
true
a.instance_of? Numeric
false
当对象是给定类的实例(而非其子类或父类实例)时返回 true
puts (String.methods).sort
# Exclude methods inherited from Object class
puts (String.methods - Object.public_instance_methods).sort
String.respond_to?(:prepend)
true
String.respond_to?(:append)
false