6 phương thức xử lí Array của Ruby bạn cần phải biết
Mảng (Array) là một trong những kiểu cấu trúc dữ liệu cơ bản trong lập trình. Việc nhanh chóng vận dụng và đọc, xử lí dữ liệu từ mảng là điều khá quan trọng để xây dựng những thứ to tát hơn với máy tính. Với một thằng nhóc con như mình, trong thời gian thực tập mình đã thấy các anh dev múa lửa với ...
Mảng (Array) là một trong những kiểu cấu trúc dữ liệu cơ bản trong lập trình. Việc nhanh chóng vận dụng và đọc, xử lí dữ liệu từ mảng là điều khá quan trọng để xây dựng những thứ to tát hơn với máy tính. Với một thằng nhóc con như mình, trong thời gian thực tập mình đã thấy các anh dev múa lửa với mấy cái select, map, ... nối đuôi nhau dài dằng dặc và nhìn rối cả mắt mà cũng không hiểu nó sẽ chạy như thế nào. Nên hôm nay mình xin giới thiệu 6 phương thức xử lí mảng khá phổ biến trong Ruby mà bạn không thể bỏ qua - nếu bạn là một Ruby developer (để tránh bị hoa mắt như mình khi bước lên trên đường ray của Ruby).
Hai phương thức này trông có vẻ khá là giống nhau. Chúng cho phép bạn "lướt" qua từng phần từ và xử lí chúng.
array = [1, 2, 3] effects = array.each{ |x| x + 2 } added = array.map{ |x| x + 2 }
Kết quả:
effects = [1, 2, 3] added = [3, 4, 5]
Đây chính là sự khác biệt giữa map và each: .map sẽ return 1 mảng mới đã bị thay đổi, còn .each vẫn giữ nguyên mảng ban đầu. Vậy nên, các bạn phải cẩn thận khi dùng .map vì nó có thể gây ra tác dụng phụ: làm thay đổi luôn mảng ban đầu của bạn.
Faster and Better: .map(&:method)
Giả sử ta có 1 mảng chữ và mình muốn convert nó thành số, thì như cú pháp ở trên ta làm như sau:
numbers = ["5", "4", "8"] string_numbers = numbers.map { |number| number.to_i } => [5, 4, 8]
Nhưng có 1 cách nhanh gọn lẹ hơn nữa, đó là dùng cú pháp .map(&:method) :
string_numbers = numbers.map(&:to_i) => [5, 4, 8]
Ngắn hơn rất nhiều phải không nào?
.select giúp bạn tìm các phần tử thoả mãn điều kiện trong mảng. Bạn cần đưa cho .select một câu điều kiện trả về true/false, .select sẽ giúp bạn lấy ra các phần tử thoả mãn điều kiện đó.
2.5.1 :011 > array = ['framgia', 'beetsoft', 'fsoft'] 2.5.1 :013 > array.select{|word| word.length == 8} => ["beetsoft"]
reject là phương thức ngược lại của select. Thử một ví dụ kết hợp reject và map với nhau xem nào:
girls = [ {name: "Bích Phương", height: 165}, {name: "Jun Vũ", height: 170}, {name: "Phương Ly", height: 172} ]
Bây giờ chúng ta muốn "quăng" đi những cô gái cao bằng hoặc dưới 1m70:
girls.reject { |girl| girl[:height] <= 170 }.map { |girl| girl[:name] } => ["Phương Ly"]
Thay vì chọn những phần tử thoả mãn điều kiện như select, chúng ta sẽ loại bỏ mọi thứ không thoả mãn điều kiện đã cho. Mọi phần tử thoả mãn điều kiện sẽ bị loại bỏ đi (như Bích Phương và Jun Vũ ở ví dụ trên vậy).
Reduce có cấu trúc hơi phức tạp 1 xíu so với các phương thức mà mình đã giới thiệu, tuy nhiên nó thường được sử dụng trong các vấn đề tính toán cộng trừ nhân chia các thứ trong Ruby. Lần này, chúng ta quan tâm rằng sau mỗi lần chạy, mảng đó sẽ return lại cái gì. Ví dụ ngay và luôn:
- Tính tổng trong mảng
array = [1, 2, 3] array.reduce{|sum, x| sum + x} => 6
- Cũng tương tự với mảng String
bands = ["nirvana", "queen", "sabbath"] bands.reduce { |sum, band| sum+band } => "nirvanaqueensabbath"
Chúng ta có thể truyền tham số mặc định cho reduce để xác định giá trị ban đầu:
array = [1, 2, 3] array.reduce(4) { |sum, x| sum+x } => 10
Faster and Better: .reduce(default value, :operation)
array = [1, 2, 3] array.reduce(4, :+) => 6
Lưu ý nhỏ: Nếu bạn thực hiện với kiểu dữ liệu không phải là số hoặc chuỗi, bạn sẽ phải khai báo giá trị ban đầu trong tham số của reduce:
employees = [{team: "Ruby", number: 8}, {team: "ReactNative", number: 6}] # Truyền giá trị ban đầu bằng 0 employees.reduce(0) {|sum, employee| sum + employee[:number] } => 14 # Không truyền giá trị mặc định employees.reduce{|sum, employee| sum + employee[:number] } **NoMethodError (undefined method `+' for {:team=>"Ruby", :number=>8}:Hash)**
Đúng như tên gọi của nó, join là một phương thức để giao lưu và kết hợp nối các phần tử trong mảng lại với nhau. join khá là giống với reduce ngoại trừ việc nó có syntax sạch sẽ hơn. Join cần 1 đối số truyền vào - chuỗi sẽ được chèn giữa các phần tử được nối của mảng. Join sẽ tạo ra một chuỗi string dàiiiiiiii bất kể bạn đưa cho nó những-thứ-không-phải-String. Xem qua ít ví dụ nào:
places = Place.all.limit 3 places.join(" ") => "#<Place:0x00005645c39f9200> #<Place:0x00005645c39f9070> #<Place:0x00005645c39f8c38>"
cars = [{type: 'porsche', color: 'red'}, {type: 'mustang', color: 'orange'}] cars.join(" and ") => "{:type=>"porsche", :color=>"red"} and {:type=>"mustang", :color=>"orange"}"
Qua bài viết này, mình hi vọng các bạn có thể hiểu hơn về các phương thức xử lí trong Ruby, đặc biệt là các bạn newbie đang bắt đầu học Ruby / Rails. Ngoài ra còn có khá nhiều phương thức mà mình chưa nhắc đến ở đây như reject, sort, ... Các bạn có thể tìm hiểu thêm tại Ruby doc. Đây là lần đầu mình dịch và viết bài nên sẽ có nhiều sai sót, mong mọi người góp ý để bài viết của mình thêm hoàn thiện hơn ạ.
Tham khảo:
https://medium.freecodecamp.org/six-ruby-array-methods-you-need-to-know-5f81c1e268ce https://ruby-doc.org/core-2.5.3/Array.html