12/08/2018, 16:12

Các phương thức thường dùng với mảng trong Ruby

Chúng ta làm việc với mảng (array) gần như là hàng ngày. Mảng rất dễ sử dụng và gần như không có vấn đề gì khó nhằn cả. Tuy nhiên có một số phương thức (method) khá là thú vị và tiện lợi mà mình muốn tổng hợp trong bài viết này. Hãy bắt đầu với một mảng arr = [1, 2, 3] arr[9] = 'foo' p arr # ...

Chúng ta làm việc với mảng (array) gần như là hàng ngày. Mảng rất dễ sử dụng và gần như không có vấn đề gì khó nhằn cả. Tuy nhiên có một số phương thức (method) khá là thú vị và tiện lợi mà mình muốn tổng hợp trong bài viết này. Hãy bắt đầu với một mảng

arr = [1, 2, 3]
arr[9] = 'foo'
p arr # => [1, 2, 3, nil, nil, nil, nil, nil, nil, "foo"]

Ruby sẽ tự động điều chỉnh chiều dài của mảng và thay những phần tử còn thiếu bằng giá trị nil

Tạo mảng

arr = Array.new # => []

Nó cũng giống như viết arr = []. Chúng ta có thể quy định kích thước và giá trị mặc định cho mảng bằng cách

arr = Array.new(3, 'foo') # => ["foo", "foo", "foo"]
arr[6] = 'bar'
p arr # => ["foo", "foo", "foo", nil, nil, nil, "bar"]

Như chúng ta thấy Ruby đã gán giá trị "foo" cho các thành phần của mảng khi khởi tạo. Tuy nhiên, khi cần thay đổi độ dài của mảng, Ruby sẽ dùng giá trị nil làm giá trị mặc định. Chúng ta có thể dùng block để tạo giá trị cho mảng

arr = Array.new(3) { |i| "item-#{i}" }
p arr # => ["item-0", "item-1", "item-2"]

Bởi vì khi khởi tạo, các giá trị của mảng có cùng chung một giá trị mặc định, nên ta có thể gặp phải vấn đề sau

arr = Array.new(2, Hash.new)
p arr # => [{}, {}]
arr[0][:foo] = 'bar'
p arr # => [{:foo=>"bar"}, {:foo=>"bar"}]

Thật thú vị khi ta chỉ thay đổi giá trị đầu tiên trong mảng nhưng nó cũng thay đổi luôn giá trị thứ hai. Đó là bởi vì chúng được xem như cùng một hash Để giải quyết vấn đề này, chúng ta nên tạo một hash cho mỗi phần tử của mảng

arr = Array.new(2) { Hash.new }
p arr # => [{}, {}]
arr[0][:foo] = 'bar'
p arr # => [{:foo=>"bar"}, {}]

Giờ mỗi phần của từ mảng được coi như một mảng riêng. Nếu bạn muốn gói vài giá trị vào trong một mảng, bạn có thể sử dụng

arr = Array(3) # => [3]
arr = Array([1,2,3]) # => [1,2,3]

Cắt (Slicing)

Mảng bao gồm cả module Enumerable, vì vậy nó có tất cả các phương thức tiện lợi, giống như: find, map, inject,... Để cắt, lấy một phần tử trong mảng, ta dùng phương thức slide hoặc [], nó hoạt động giống nhau

arr = [1,2,3,4]
arr[0]  # => 1
arr[20] # => nil

Có thể truyền thêm biến thứ 2 quy định độ dài

arr = [1,2,3,4]
arr[0, 2]  # => [1, 2]

Ở đây hiểu là lấy 2 phần tử bắt đầu từ phần tử được đánh thứ tự là 0 Có thể truyền vào một khoảng

arr = [1,2,3,4]
p arr[0..2] # => [1, 2, 3]

Tất cả mọi trường hợp đều trả về một mảng mới, nhưng nếu bạn muốn thay đổi mảng hiện tại, dùng phương thức slide!

arr = [1, 2, 3]
arr.slice!(1, 2) # => [2, 3]
p arr # => [1]

Ở đây ta đã cắt đi phần tử [2, 3] của mảng arr nên mảng arr chỉ còn lại một phần tử [1]

Chèn (Inserting)

Ta sẽ dùng cách này để chèn một giá trị vào mảng

arr = [1,2,3]
arr.insert(1, [10, 20])
p arr # => [1, [10, 20], 2, 3]

Nó chèn mảng [10, 20] thành giá trị thứ hai trong mảng arr. Nếu bạn chỉ muốn chèn số, ta dùng thêm flatten!

arr.insert(1, [10, 20]).flatten! # => [1, 10, 20, 2, 3]

Hoặc dùng toán tử *, cách này ngắn gọn hơn

arr = [1,2,3]
arr.insert(1, *[10, 20]) 
p arr # => [1, 10, 20, 2, 3]

Để thay thế một hoặc nhiều giá trị bởi giá trị từ mảng khác, ta dùng cách này

arr = [1,2,3]
arr[0..0] = [10, 20]
p arr # => [10, 20, 2, 3]

So sánh mảng

Để so sánh mảng, chúng ta sử dụng toán tử <=>. So sánh sẽ trả về số nguyên (-1, 0, hoặc +1) nếu mảng đó nhỏ hơn, bằng, hoặc lớn hơn mảng còn lại. Khi so sáng mảng, Ruby so sánh lần lượt từng phần tử, ví dụ

arr = [1,2,3]
another_arr = [1,2,4]

arr <=> another_arr # => -1

Ruby so sánh: 1 ở arr với 1 ở another_arr, sau đó là 2 với 2, và 3 nhỏ hơn 4, vì vậy trả về giá trị -1 có nghĩa arr < another_arr. Nếu tất cả các phần tử đều giống nhau sẽ trả về 0

arr = [1, 2, 3]
another_arr = [1, 2, 3]

arr <=> another_arr # => 0

Nếu bất kì phần tử nào trong mảng đầu tiền lớn hơn phần tử tương ứng trong mảng còn lại, nó sẽ trả về 1

arr = [1, 5, 3]
another_arr = [1, 2, 3]

arr <=> another_arr # => 1 (5 lớn hơn 2)

Còn nếu phần tử trong mảng không so sánh được? Hãy xem

arr = [1, 5, 3]
another_arr = [1, "test", 3]

arr <=> another_arr # => nil

Nếu Ruby không thể so sánh 2 phần tử, nó sẽ trả về nil Còn nếu kích thước 2 mảng khác nhau?

arr = [1, 2, 3]
another_arr = [1, 2, 3, 4]

p arr <=> another_arr # => -1

Nếu độ dài của mảng đầu tiên nhỏ hơn độ dài của mảng còn lại, nó sẽ trả về -1, ngược lại sẽ trả về 1

arr = [1, 2, 3, 4, 5]
another_arr = [1, 2]

arr <=> another_arr # => 1

Bài viết khá đơn giản nhưng mong rằng hữu ích với bạn. Cảm ơn đã theo dõi!

0