BẮT ĐẦU
KIỂU DỮ LIỆU
TOÁN TỬ
NÂNG CAO
INTERVIEW
CÁC CHỦ ĐỀ
BÀI MỚI NHẤT
Dự án mới của mình là gamehow.net, mời anh em ghé thăm và góp ý ạ.

Iterator trong Ruby

Ở bài trước mình có nói với các bạn về việc sử dụng các vòng lặp for, vòng lặp while, hay until. Chúng rõ ràng là những cốt lõi trong ngôn ngữ lập trình Ruby, thế nhưng những cách viết vậy có lẽ vẫn hơi thủ công và cồng kềnh. Trong bài này mình sẽ giới thiệu với các bạn các cách để làm việc với vòng lặp dễ dàng và nhanh hơn

1. Iterator là gì?

Iterators là các công cụ vòng lặp giúp chúng ta thực hiện truy cập vào các phần tử của một tập các đối tượng một cách tuần tự.

banquyen png
Bài viết này được đăng tại freetuts.net, không được copy dưới mọi hình thức.

Cụ thể ở đây Ruby cung cấp cho chúng ta các phương thức để làm việc với các collection như là Array hay là Hash. Collection giúp chúng ta lưu dữ một tập hợp các dữ liệu.

Có rất nhiều các iterator trong Ruby đã được định nghĩa sẵn như each, map, select, find... Để có thể hiểu rõ hơn rằng khi nào dùng iterator nào thì chúng ta sẽ lần lượt đi tìm hiểu các iterator này nhé.

2. Các iterators trong Ruby

each

each cũng giống như cách mà chúng ta làm việc với các vòng lặp thông thường như for, while hay until. Nó sẽ lần lượt truy cập tới các phần tử trong collection. Và vấn đề đáng lưu tâm nhất ở đây là each sẽ trả về mảng ban đầu chứ không phải là mảng kết quả.

Cú pháp

collection.each do |variable_name|
   # code
end

hoặc nếu những đoạn code bên trong đơn giản chúng ta có thể viết tắt như này, điều này sẽ áp dụng tương tự cho các iterator khác.

collection.each {|variable_name| // code }

collection ở đây các bạn có thể truyền vào là một Range, Array hoặc Hash đều được cả nhé.

[1, 2, 3, 4].each do |e|
  puts e * 2
end

Kết quả:

2
4
6
8

Tại sao mà mình là nói là each sẽ trả về mảng ban đầu thay vì mảng kết quả. Ví dụ nếu chúng ta muốn lấy ra các phần tử có giá trị lớn hơn 2 trong mảng chả hạn với each thì theo như logic chúng ta sẽ viết như thế này

a = [1,2, 3, 4]

a.each do |e|
  e > 2
end

puts "Mang a #{a}"

Kết quả

Mang a [1, 2, 3, 4]

Nên là nếu như chúng ta muốn lấy vài phần tử trong mảng cho trước thì dùng each sẽ không phù hợp.

map

Khác với each, thì kết quả của map sẽ trả về một mảng mới sau khi đã lặp qua các phần tử của một collection, kết quả trả về sẽ tùy thuộc vào cách mà chúng ta xử lý collection đó. Nhưng mà lưu ý là mảng ban đầu sẽ không thay đổi giá trị nhé.

Cú pháp:

collection.map do |variable_name|
   # code
end

Ví dụ

[1,2, 3, 4].map do |e|
   e * 2
end

Kết quả

2
4
6
8

Nếu như chúng ta muốn lấy các giá trị mà thỏa mãn với các điều kiện cho trước thì kết quả sẽ trả về là một mảng các giá trị true hoặc false

[1,2,3,4,5,6,7,8,9,10].map{ |e| e > 5 }

Kết quả

false
false
false
false
false
true
true
true
true
true

select

select cũng là một trong những iterator phổ biến thường được dùng. Nó sẽ lặp qua lần lượt các phần tử trong collection và trả về 1 mảng mới thỏa mãn điều kiện được định nghĩa trong block.

Cú pháp

collection.select do |variable_name|
   # code
end

Giả sử chúng ta muốn trả về các kết quả nếu giá trị nhỏ hơn 5 thì sử dụng select sẽ trả lại cho kết quả hợp lý

[1,2,3,4,5,6,7,8,9,10].select{ |e| e > 5 }

Kết quả

6, 7, 8, 9, 10

Chúng ta không thể lặp lại mảng rồi thay đổi giá trị của các phần tử trong mảng nếu như sử dụng select

[1,2,3,4,5,6,7,8,9,10].select{ |e| e * 5 }

Kết quả

1,2,3,4,5,6,7,8,9,10

collect

collect thì về cơ bản là giống map. Nó cũng lặp qua lần lượt các phần tử trong mảng và thực hiện các biểu thức trong block

[1,2, 3, 4].collect {|e| e * 2}

Kết quả

2, 4, 6, 8

Nó cũng sẽ trả về một mảng các giá trị true hoặc false nếu như chúng ta chọn các giá trị theo điều kiện

[1, 2, 3, 4].collect {|e| e > 5}

Kết quả

false, false, false, false

inject

inject sẽ giúp chúng ta tính tổng các giá trị trong mảng.

inject có thể nhận tham số truyền vào là một giá trị nào đó. Nếu như chúng ta không truyền giá trị nào thì mặc định tổng ban đầu của mảng sẽ lấy giá trị đầu tiên của mảng làm tổng. Nếu truyền giá trị khác thì tổng ban đầu của mảng sẽ bằng giá trị chúng ta truyền vào.

Ví dụ

[1,2,3,4,5,6,7,8,9,10].inject{ |sum, e| sum += e }

Kết quả

55

Nếu chúng ta truyền thêm tham số vào inject

[1,2,3,4,5,6,7,8,9,10].inject(15){ |sum, e| sum += e }

Kết quả

70

detect

detect là một iterator khá hay, nó sẽ trả về giá trị đầu tiên thỏa mãn điều kiện trong block

[1,2,3,4,5,6,7,8,9,10].detect{ |e| e > 4 }

Kết qủa

5

Nếu như biểu thức bên trong block không phải là một điều kiện thì mặc định nó sẽ trả về phần tử đầu tiên của mảng

[1,2,3,4,5,6,7,8,9,10].detect{ |e| e * 2 }

Kết quả

1

Ngoài hàm detect này ra thì chúng ta còn có hàm find với chức năng tương tự

[1,2,3,4,5,6,7,8,9,10].find{ |e| e > 4 }

Kết quả

5

Có thể thấy, find và detect sẽ đều không lặp quả tất cả các phần tử nếu như một phần tử trong mảng thỏa mãn điều kiện, thì vòng lặp này kết thúc luôn. Việc này chúng ta cũng có thể liên tưởng khi sử dụng break để thoát khỏi vòng lặp.

each_with_index

each_with_index thì tương tự với phương thức each mà mình đã nói tới ở trên. Tuy nhiên với each_with_index cho phép chúng ta truyền thêm một tham số nữa, đó là chỉ số (index) của các phần tử mảng. Trong rất nhiều các trường hợp mà chúng ta sẽ cần tới cái index này.

Cú pháp

collection.each_with_index {|item, index| // code }

Ví dụ

[1,2,3,4,5].each_with_index { |item, index| puts "index: #{index} for #{item}" }

Kết quả

index: 0 for 1
index: 1 for 2
index: 2 for 3
index: 3 for 4
index: 4 for 5

times

Iterator times này chúng ta sẽ không áp dụng trên các collection như các phương thức ở trên, mà với iterator này chúng ta sẽ áp dụng trên một số. Có nghĩa là chúng ta sẽ lặp lại một đoạn code với số lần mà chúng ta định nghĩa

Cú pháp

number.times do
  //code
end

Ví dụ

5.times do 
  puts "Hello"
end

Kết quả

Hello
Hello
Hello
Hello
Hello

3. Kết luận

Qua bài viết này chúng ta có thể thấy được sức mạnh của các iterator trong Ruby là như thế nào. Đây là những iterator rất phổ biến và hay được sử dụng trong việc coding. Hãy kiểm tra kĩ các trường hợp mà bạn cần xử lý để áp dụng các iterator một cách chính xác và nhanh gọn nhất có thể. Iterator trong Ruby là rất phong phú và đa dạng nên hãy áp dụng nó thay vì viết các vòng lặp đơn thuần như for, while, until vì đôi khi chúng hơi làm "phình to" code của chúng ta.

Cùng chuyên mục:

Block trong Ruby

Block trong Ruby

Block là một khối lệnh được đặt trong ...

Vòng lặp trong Ruby: Vòng lặp for / while / until / loop

Vòng lặp trong Ruby: Vòng lặp for / while / until / loop

Khi học một ngôn ngữ lập trình thì không thể không tìm hiểu tới một…

Câu lệnh điều kiện trong Ruby

Câu lệnh điều kiện trong Ruby

Trong bài này chúng ta sẽ học các lệnh điều kiện trong Ruby, đây là…

Các toán tử trong Ruby

Các toán tử trong Ruby

Nói đến toán tử thì dù bạn học ngôn ngữ nào đi nữa thì việc…

Cách sử dụng Ranges trong Ruby

Cách sử dụng Ranges trong Ruby

Ví dụ bạn cần tạo ra một dãy từ 1 đến 100 thì có thể…

Cách sử dụng Array trong Ruby

Cách sử dụng Array trong Ruby

Đây cũng là một trong những kiểu dữ liệu phổ biến nhất, vì vậy bạn…

Kiểu dữ liệu Symbol trong Ruby

Kiểu dữ liệu Symbol trong Ruby

Symbol giống như một String thế nhưng Symbol là một chuỗi bất biến nghĩa là…

Kiểu dữ liệu Text trong Ruby (còn gọi là chuỗi / string)

Kiểu dữ liệu Text trong Ruby (còn gọi là chuỗi / string)

Kiểu dữ liệu Boolean trong Ruby: True, False và Nil

Kiểu dữ liệu Boolean trong Ruby: True, False và Nil

Boolean là kiểu dữ liệu rất quan trọng, nó được dùng rất nhiều trong những…

Kiểu dữ liệu Hashes trong Ruby: Hiểu từ đơn giản đến phức tạp

Kiểu dữ liệu Hashes trong Ruby: Hiểu từ đơn giản đến phức tạp

Nếu bạn đã từng làm việc với một vài ngôn ngữ khác trước khi mà…

Hiểu về Method Missing trong Ruby

Hiểu về Method Missing trong Ruby

Chắc hẳn với các lập trình viên chúng ta ai cũng có thể đôi lần…

Kiểu dữ liệu Number trong Ruby (Kiểu số Integer, Float, ...)

Kiểu dữ liệu Number trong Ruby (Kiểu số Integer, Float, ...)

Trước tiên, chúng ta cùng nhìn qua một bức ảnh tổng quát phân cấp các…

Ruby là gì? Ai đã sáng tạo ra ngôn ngữ viêm kim cương này?

Ruby là gì? Ai đã sáng tạo ra ngôn ngữ viêm kim cương này?

Từ những năm 2008, thời mà mình còn học đại học thì Ruby là ngôn…

Các loại biến và cách sử dụng Module trong Ruby

Các loại biến và cách sử dụng Module trong Ruby

Bất kì một ngôn ngữ lập trình nào đều có khái niệm biến và ruby…

Cách tạo Method - Class và Object trong Ruby

Cách tạo Method - Class và Object trong Ruby

Trong bài này mình sẽ hướng dẫn các bạn cách tạo hàm, gọi hàm. Cách…

Cú pháp trong Ruby - Chạy Hello World

Cú pháp trong Ruby - Chạy Hello World

Tổng quan về cú pháp trong ruby. Hướng dẫn tạo file và chạy hello world…

Hướng dẫn cài đặt Ruby trên Window, Linux và MacOS

Hướng dẫn cài đặt Ruby trên Window, Linux và MacOS

Hướng dẫn chi tiết cách thiết lập môi trường lập trình Ruby trên hệ điều…

Top