- vừa được xem lúc

Ôn thi Ruby Silver

0 0 28

Người đăng: Hoàng Đức Quân

Theo Viblo Asia

Như tiêu đề, mình đang muốn học lại Ruby để 1 là kiếm chứng chỉ Ruby Silver, 2 là bổ sung thêm những phần kiến thức chưa biết về Ruby nên ta có bài này.

Ở đây sẽ có ưu ái hẳn hoi 1 bài mẫu luôn để mọi người cũng chiêm ngưỡng.

a = [1, 2, 3, 5, 8]
b = [1, 3, 6, 7, 8]
c = false || true ? true && false ? a | b : a & b : b ;
p c

Trên đây là cơn choáng mình nhận được vì lỡ học khuya lúc 12 giờ đêm. Và để phân tích nó thì chúng ta sẽ cùng đi lại vài kiến thức Ruby cơ bản.

Các toán tử

Toán tử đại số

Toán tử Ý nghĩa Ví dụ
+ Toán tử cộng 10 + 20 trả về 30
Toán tử trừ 10 - 20 trả về -10
* Toán tử nhân 10 * 20 trả về 200
/ Phép chia lấy phần nguyên 20 / 10 trả về 2
% Phép chia lấy phần dư 20 % 10 trả về 0
** Luỹ thừa 10**20 sẽ trả về 102010^{20}

Ví dụ đơn giản:

def foo(n) n ** n
end puts foo(3) * 2

Ta có 3323^ 3 * 2 bằng 54.

Toán tử so sánh

Các toán tử này dùng để so sánh giá trị của 2 phần tử

Toán tử Ý nghĩa Ví dụ
== Trả về true nếu bằng nhau 10==10.0 trả về true
!= Trả về true nếu khác nhau 10!=10.0 trả về false
> Trả về true nếu giá trị trước lớn hơn giá trị sau 10>5 trả về true
< Trả về true nếu giá trị trước nhỏ hơn giá trị sau 10<20 trả về true
>= Trả về true nếu giá trị trước lớn hơn hoặc bằng giá trị sau 10>=10.0 trả về true
<= Trả về true nếu giá trị trước nhỏ hơn hoặc bằng giá trị sau 10<=10.0 trả về true
<=> So sánh gộp. 0 nếu bằng nhau, 1 nếu giá trị trước lớn hơn và -1 nếu giá trị trước nhỏ hơn 10<=>20 sẽ trả về -1
=== Cũng là check giá trị bằng nhau như mà nó lạ .... à không lạ lắm. Toán tử này hay dùng trong các câu lệnh điều kiện if-else và case-when 10===10.0 trả về true
eql? Check không chỉ giá trị mà còn kiểu dữ liệu của 2 phần tử so sánh 10.eql?10.0false. Giá trị bằng nhau nhưng type intfloat là khác nhau
equal? Trả về true nếu 2 phần tử có chung object id a="xyz", b="xyz" nhưng a.equal?bfalse

Ví dụ:

  • Cho a = 10, b = 10.0. a==ba===b trả về cùng giá trị true còn a.eql?ba.equal?b cùng là false.

Toán tử gán

Phần này giống với toán tử toán học 1 chút, nên mình sẽ lướt qua. = là gán giá trị, ví dụ a = b là gán giá trị b bằng với a, còn a += b thì tức là a = a + b

Toán tử song song

Thay vì làm như này

a = 10
b = 20
c = 30

Chúng ta có thể gán nhanh như này

a, b, c = 10, 20, 30

Với cách này, ta có thể dùng để hoán đổi giá trị

a, b = b, c

Sự khác nhau của s..es...e

s..e là lấy các phần tử từ s tới cả e, còn s...e là lấy các phần tử từ s tới trước e. Ví dụ: 10..15[10, 11, 12, 13, 14, 15] 10...15[10, 11, 12, 13, 14]

Toán tử logic

Toán tử Ý nghĩa Ví dụ
&& hay and Toán tử logic AND. Trả về kết quả true khi cả 2 phần tử đều đúng 10 && 20 trả về true
|| hay or Toán tử logic OR. Trả về kết quả true khi cả 1 phần tử đúng 10 || 20 trả về true
! hay not Toán tử logic NOT. Trả về kết quả ngược lại với điều kiện !(10 && 20) sẽ trả về false

Mảng

Các toán tử của mảng

Giao của 2 mảng& :

[ "a", "b", "c" ] & [ "c", "d", "a" ] #=> [ "a", "c" ]

Hợp của 2 mảng | :

[ "a", "b", "c" ] | [ "c", "d", "a" ] #=> [ "a", "b", "c", "d" ]

Và cái dễ nhầm là đây. PHẢI NHỚ RẰNG 1 DẤU THÌ MỚI CÓ NGHĨA KIA, CÒN 2 DẤU THÌ SẼ KHÁC || là chỉ lấy mảng trái, không lấy mảng phải

[ "a", "b", "c" ] || [ "c", "d", "a" ] #=> [ "a", "b", "c" ]

&& là chỉ lấy mảng phải, không lấy mảng trái

[ "a", "b", "c" ] && [ "c", "d", "a" ] #=> [ "c", "d", "a" ]

slice

# create arrays
array1 = [1, 2, 3, 4, 5]
array2 = ["a", "b", "c", "d", "e"]
array3 = ["cat", "dog", "cow", "rat", "fox"]
array4 = [true, false, nil]
array5 = ["", "nil", "false", "true"] # call `slice()` method and save returned sub-arrays
a = array1.slice(1) # 2nd element
b = array2.slice(2, 3) # from 3rd element, return 3
c = array3.slice(1, 1) # from 2nd element, return only 1
d = array4.slice(0, 5) # from 1st element, return all elements
e = array5.slice(2) # return 3rd element # print returned values
puts "#{a}" # 2
puts "#{b}" # ["c", "d", "e"]
puts "#{c}" # ["dog"]
puts "#{d}" # [true, false, nil]
puts "#{e}" # false

each_slice và each_cons

  • each_slice :
(1..10).each_slice(3) {|arr| p arr } # [1, 2, 3]
# [4, 5, 6]
# [7, 8, 9]
# [10]
  • each_cons :
(1..10).each_cons(3) {|arr| p arr } # [1, 2, 3]
# [2, 3, 4]
# [3, 4, 5]
# [4, 5, 6]
# [5, 6, 7]
# [6, 7, 8]
# [7, 8, 9]
# [8, 9, 10]

push, pop, shift và unshift

  • push Thêm 1 phần tử vào cuối mảng
s = ["one", "two", "three"]
s.push "four" # ["one", "two", "three", "four"]
  • pop Xóa phần tử cuối mảng
s = ["one", "two", "three"]
s.pop # ["one", "two"]
  • shift Xóa phần tử đầu mảng
s = ["one", "two", "three"]
s.shift # ["two", "three"]
  • unshift Thêm phần tử nil vào đầu mảng
s = ["one", "two", "three"]
s.unshift # [nil, "one", "two", "three"]

find_all, select, detect, collect, map

  • find_all, select : Trả về tất cả các phần tử của mảng thỏa mãn yêu cầu nào đó
  • detect : Trả về giá trị đầu tiên thỏa mãn điều kiện nào đó
  • collect, map: Trả về mảng thỏa mãn điều kiện đã cho

flatten, flatten! và reverse

  • flatten: Chuyển đổi cấu trúc của mảng từ mảng nhiều chiều thành mảng 1 chiều
[["apple"],["banana"],["orange"]].flatten #=> ["apple", "banana", "orange"]
  • flatten!: cũng là flatten nhưng nó không chỉ khác trên ở dấu !. Nếu mảng bị flatten là 1 chiều thì trả về nil
[["apple"],["banana"],["orange"]].flatten! #=> ["apple", "banana", "orange"]
["apple", "banana", "orange"].flatten! #=> nil
  • reverse: Đảo chiều mảng đã cho
["apple", "banana", "orange"].reverse #=> ["orange", "banana", "apple"]

product và zip

  • product: trả về mảng chứa tổ hợp của phần tử của các mảng thành phần
[1,2].product([3,4]) #=> [[1,3],[1,4],[2,3],[2,4]]
  • zip: trả về mảng tuyến tính từng phần tử
[1,2].zip([3,4]) #=> [[1, 3], [2, 4]]

tranpose

Đại loại thì nó như sau

[[1, 3], [1, 4], [2, 3], [2, 4]
].transpose #=> [[1, 1, 2, 2], [3, 4, 3, 4]]

Hash

Hash là 1 cấu trúc cho phép map từng key với từng giá trị

Ví dụ:

h = {:foo => 0, :bar => 1, :baz => 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

Chúng ta có thể chơi cú pháp kiểu JSON:

h = {foo: 0, bar: 1, baz: 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

Hoặc dùng chuỗi:

h = {'foo': 0, 'bar': 1, 'baz': 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

Xào nấu thập cẩm:

h = {foo: 0, :bar => 1, 'baz': 2}
h # => {:foo=>0, :bar=>1, :baz=>2}

invert

invert là method cho phép hoán đổi key và value

h = {a: 100, b: 200}
puts h.invert #=> {100=>:a, 200=>:b}

Nếu trước khi invert 2 key có cùng value thì sau khi invert, giá trị sau cùng sẽ được lấy

h = {a: 100, b: 100}
puts h.invert #=> {100=>:b}

each

Dùng method each với Hash sẽ trả ra kiểu Array

h = {a: 100}
h.each {|p| p p.class
}
# => Arry

Chú ý

hash = {klass => 100}

tương đương

hash = {}
hash.store(klass, 100)

tương đương

hash = Hash[klass, 100]

Chuỗi

%|apple banana orange| #=> "apple banana orange"

split

Chia 1 chuỗi ra thành các chuỗi con dựa theo kí tự phân tách. Trả về 1 mảng chứa các chuỗi con. Mặc định của ký tự phân tách là ' '

p "Apple Banana Lemon".split #=> ["Apple", "Banana", "Lemon"]
p "Apple Banana Lemon".split ' ' #=> ["Apple", "Banana", "Lemon"]
p "Apple Banana Lemon".split / / #=> ["Apple", "Banana", "Lemon"]
p "Apple Banana Lemon".split /( )/ #=> ["Apple", " ", "Banana", " ", "Lemon"]

Hãy lưu ý dấu ngoặc đơn.

strip!, chomp! và chop!

  • strip: xoá hết các kí tự trắng được định nghĩa trong Ruby \t\r\n\f\v
str = "Liberty Fish \r\n"
str.strip!
#=> "Liberty Fish"
  • chomp!: xoá đi kí tự hết dòng
str = "Liberty Fish \r\n"
str.chomp!
#=> "Liberty Fish "
  • chop!: xoá kí tự cuối của chuỗi. Nhưng nếu là "\r\n" thì xoá cả 2
str = "Liberty Fish \r\n"
str.chop!
#=> "Liberty Fish "
str = "Liberty Fish \r\n"
str.chop!
#=> "Liberty Fis"

Heredoc

Kết quả trả về của 1 chuỗi nhiều dòng sẽ chỉ tới ký tự Heredoc là hết

data = <<EOF
Hello,
World
EOF
"EOF"
#=> "Hello,\nWorld\n"

Time

Chủ yếu phần này sẽ hay hỏi ở strftime

Time + số

Các dạng Time + 1 số nào đó thì sẽ đều là chỉ số giây

strftime

Ký hiệu Ý nghĩa
%y Năm dạng tắt(ví dụ: 22)
%Y Năm dạng đủ(ví dụ: 2022)
%m Tháng(01-12)
%M Số phút(00-59)
%d Ngày(01-31)
%D, %x Ngày tháng năm dạng %m/%d/%y
%F %Y-%m-%d

Ví dụ: Date.today.to_s tương đương với Date.today.strftime("%Y-%m-%d") và tương đương Date.today.strftime(%F)

File

dirname

dirname là method dùng để chỉ directory ngoài cùng của file

File.dirname("text.txt") # => "."
File.dirname("REx/text.txt") # => "REx"
File.dirname("Desktop/REx/text.txt") # => "Desktop/REx"

File.open và các param

Đây cũng là 1 phần quan trọng. Nếu nắm được và nhớ được thì có thể ghi điểm Với code File.open('the_file_name.txt', XXXX) thì tuỳ từng param ở vị trí XXXX sẽ có những xử lý như sau

Param Ý nghĩa
'r' Chỉ đọc file
'r+' Đọc file và ghi đè
'w' Tạo mới và ghi đè(đọc sẽ báo lỗi not opened for reading (IOError))
'w+' Tạo mới, đọc và ghi đè
'a' Chỉ ghi thêm(đọc sẽ báo lỗi not opened for reading (IOError))
'a+' Đọc và ghi thêm

Dir

pwd

pwd trả về tên của client directory

Dir.pwd # => "/Users/user/RubyExamination"

Thread

Có 3 cách để tạo 1 Thread mới: Thread.new, Thread.startThread.fork

Biến

  • Hằng số trong Ruby bắt đầu bằng chữ cái alphabet viết in hoa: CONST1 = 129
  • Biến global trong Ruby bắt đầu bằng $: $var = "global"
  • Biến instance trong Ruby bắt đầu bằng @: @var = "instance"
  • Biến class trong Ruby bắt đầu bằng @@: @@var = "class". Phải được khởi tạo trước khi gọi trong method. Gọi 1 biến class chưa được định nghĩa sẽ xảy ra lỗi.

Class trong Ruby

Đây là phần chắc chắn là đau đầu trong tương lai nếu chúng ta thi chứng chỉ Ruby Gold. Ở mức Silver mới dừng ở những khái niệm cơ bản Module, Class thôi =)))

Cách định nghĩa Class và Module

Well, phần rất đơn giản thật =)) nhưng khi bạn có trộn thêm tí JS, Python để làm serverless trên AWS và thi thoảng phải động vào C# hay Java thì bạn đúng nghĩa là 1 Trại tâm thần đa ngôn ngữ.... lập trình :3 Nên cứ memo vào cho nó chắc để đỡ mất điểm oan

Định nghĩa module:

module MyModule ...
end

Định nghĩa class:

class MyClass ...
end

attr_accessor, attr_writer & attr_reader

attr_accessor:

class Foo attr_accessor :a
end

tương đương với

class Foo # getter def a @a end # setter def a=(val) @a = val end
end

Ta có thể gọi nhanh

foo = Foo.new
foo.a, foo.b = "aaa", "bbb" puts foo.a # => aaa
puts foo.b # => bbb

attr_reader:

class Foo attr_reader :a def initialize @a = "REx" end
end

tương đương với

class Foo # getter def a @a end def initialize @a = "REx" end
end

khi đó

foo = Foo.new
puts foo.a #=> 'REx'

attr_writer:

class Foo attr_writer :a
end

tương đương với

class Foo # setter def a=(val) @a = val end
end

Exception

begin raise
rescue => e puts e.class
end

Mặc định đoạn code này trả về RuntimeError. Tuy nhiên, nếu sau raise thiết lập error khác thì e.class sẽ là error thiết lập

begin raise ArgumentError
rescue => e puts e.class # => ArgumentError
end

Quay lại bài toán ban đầu

c = false || true ? true && false ? a | b : a & b : b ;

có thể phân tích rõ thành c = (false || true) ? ((true && false) ? (a | b) : (a & b)) : b ;

Với false || true luôn trả kết quả true nên c = (true && false) ? (a | b) : (a & b)

false && true cũng trả kết quả true nên c = a | b

Vì vậy, với

a = [1, 2, 3, 5, 8]
b = [1, 3, 6, 7, 8]

thì c = a | b[1, 3, 8]

Một số bài tập khác

Bài tập 1

hoge = 0
def hoge x = 0 5.times do |i| x += 1 end x
end
puts hoge #=> 0

Lý do: Biến số sẽ được ưu tiên trước method

Bài tập 2

class Foo @@var = 0 def var @@var end def var=(value) @@var = value end
end class Bar < Foo
end foo = Foo.new
foo.var += 1
bar = Bar.new
bar.var += 2 puts "#{foo.var}/#{bar.var}"

Kết quả sẽ trả về 3/3 do khi viết như trên, foo.var == bar.var

Kết bài

Việc memo thế này thực ra từ kiến thức Ruby và phải nói thật là học tủ vì các method của Ruby rất nhiều và cực khó nhớ. Đây là cái do mình đọc sách, làm đề và viết lại để ghi nhớ. Rất mong các bạn có phần nào tham khảo được

Bình luận

Bài viết tương tự

- vừa được xem lúc

Bài toán tìm đường đi ngắn nhất với giải thuật Dijkstra

Với các bạn sinh viên chuyên ngành công nghệ thông tin, chắc không lạ gì với bài toán tìm đường đi ngắn nhất (Shortest Path Problems) trong đồ thị trọng số nữa. Ở bài viết lần này, mình sẽ làm 3 việc:.

0 0 135

- vừa được xem lúc

Tôi cá là bạn không biết những điều này - Ruby on rails ( Phần 2)

Các bạn có thể theo dõi phần 1 ở đây :. https://viblo.asia/p/toi-ca-la-ban-khong-biet-nhung-dieu-nay-ruby-on-rails-phan-1-WAyK8DDeKxX. 5.

0 0 222

- vừa được xem lúc

Những thay đổi trong ruby 3.0

. 2020 là một năm lớn đối với cộng đồng Ruby. Những người sáng lập Ruby có một món quà thực sự tuyệt vời cho chúng ta vào giáng sinh với việc phát hành Ruby 3.

0 0 47

- vừa được xem lúc

Có gì đặc biệt trong phiên bản Ruby 3x3 ?

Hello guys, chắc hẳn thời gian vừa rồi chúng ta cũng đã nghe qua thông tin Ruby sắp cho ra mắt Ruby version 3, hay còn được gọi là ruby 3x3, vậy liệu Ruby version 3 này có gì mới, và có những update nào đáng phải kể đến, và tại sao mọi người lại gọi nó là ruby version 3x3, thì trong bài ngày hôm nay

0 0 43

- vừa được xem lúc

Cách sử dụng class Time & Date trong Ruby (Phần 1)

Time là một class trong Ruby, nó sẽ giúp chỉnh sửa format, trích xuất thông tin một cách hiệu quả theo ý của bạn. . Topic hôm nay chúng ta có gì nào. .

0 0 97

- vừa được xem lúc

Ruby 3.0 có gì mới

Ruby 3.0.0 đã được ra mới được ra mắt vào tháng 12/2020, mục tiêu của bản 3.0.

0 0 41