Computer >> Máy Tính >  >> Lập trình >> Ruby

Sử dụng các biểu tượng để xây dựng và chia nhỏ các mảng trong Ruby

Một trong những điều tôi yêu thích ở Ruby là chiều sâu của các tính năng của nó. Bạn có thể sử dụng một toán tử, nhưng hãy tìm hiểu kỹ một chút và bạn sẽ thấy rằng bạn chỉ mới đang làm xước bề mặt của những gì nó có khả năng. Toán tử biểu tượng khiêm tốn (*** ) là một ví dụ tuyệt vời.

Bạn có thể đã sử dụng biểu tượng cho các đối số "bắt tất cả". Và đó là tất cả những gì mà hầu hết mọi người sử dụng chúng.

def go(x, *args)
  puts args.inspect
end

go("a", "b", "c")

Nếu bạn đang sử dụng cú pháp đối số từ khóa mới, hãy sử dụng biểu tượng kép như sau:

def go(**params)
  puts params.inspect
end

go(x: 100, y: 200)

Điều này rất hữu ích, nhưng bạn có thể sử dụng biểu tượng cho nhiều hơn nữa. Hãy đi sâu vào!

Sử dụng một mảng để truyền nhiều đối số

Bạn không chỉ có thể sử dụng các biểu tượng khi xác định các phương thức mà còn có thể sử dụng chúng khi gọi các phương thức. Chúng cho phép bạn truyền một mảng vào một hàm mong đợi nhiều đối số. Mục đầu tiên trong mảng trở thành đối số đầu tiên, mục thứ hai trở thành đối số thứ hai, v.v.

def go(x, y)
end

point = [12, 10]
go(*point)

Và đừng quên rằng bạn có thể sử dụng biểu tượng kép cho các đối số từ khóa kiểu mới:

def go(x:, y:)
end

point = { x: 100, y: 200 }
go(**point)

Biểu tượng không nhất thiết phải đi ở cuối

Mặc dù việc đặt các đối số rải rác của bạn ở cuối danh sách đối số là điều phổ biến, nhưng không có luật nào yêu cầu điều đó.

Bạn có thể đặt biểu tượng ở bất kỳ đâu trong danh sách đối số.

def go(x, *args, y)
  puts x # => 1
  puts y # => 5
  puts args.inspect # => [2,3,4]
end

go(1, 2, 3, 4, 5)

Cấu trúc mảng

Tất cả các thủ thuật này với các đối số chỉ là một trường hợp đặc biệt của cấu trúc mảng.

Trong trường hợp bạn không quen với thuật ngữ "hủy cấu trúc mảng", nó chỉ đơn giản có nghĩa là chia một mảng thành các mục riêng lẻ. Nó trông như thế này:

a, b = [1, 2]
puts a
# 1
puts b
# 2

Điều này hoạt động tốt nhưng có thể hơi khó khăn khi phải chỉ định một biến để giữ mọi mục duy nhất trong mảng. Toán tử biểu tượng xoay quanh vấn đề này - về cơ bản hoạt động giống như một ký tự đại diện. Hãy xem một vài ví dụ.

Bật mục đầu tiên từ một mảng

Đôi khi, rất hữu ích khi có thể bật mục đầu tiên của một mảng mà không làm thay đổi mảng ban đầu. Đó là những gì ví dụ này làm.

first, *remainder = [1, 2, 3, 4, 5]
first
# => 1
remainder
# => [2, 3, 4, 5]

Nếu bạn chỉ muốn mục đầu tiên mà không muốn phần còn lại của mảng, bạn có thể sử dụng cú pháp:

first, * = [1, 2, 3, 4, 5]
first
# => 1

Bật mục cuối cùng

Để kéo mục ra khỏi cuối mảng thay vì ở đầu, chỉ cần dán biểu tượng ở đầu như sau:

*prefix, last = [1, 2, 3, 4, 5]
last
# => 5
prefix
# => [1, 2, 3, 4]

Một lần nữa, nếu chúng ta không muốn một biến cụ thể, chúng ta không cần phải gán nó:

Lấy n mục đầu tiên và cuối cùng của một mảng

Nếu bạn đặt toán tử biểu tượng ở giữa, bạn có thể kéo một số lượng mục tùy ý ra khỏi mỗi đầu của mảng.

first, *, last =  [1, 2, 3, 4, 5]
first
# => 1
last
# => 5

Hạn chế

Khi sử dụng toán tử splat trong cấu trúc mảng, bạn vẫn phải chỉ định vị trí của các mục mảng liên quan đến phần đầu và phần cuối của mảng. Vì vậy, nó không phải là công cụ tốt nhất để trích xuất các mục từ giữa một mảng dài.

Ngoài ra, tôi dường như không thể tìm thấy bất kỳ thủ thuật thú vị nào bằng cách sử dụng biểu tượng kép (** ) để gây rối với các hàm băm. Khập khiễng!

Xây dựng mảng

Toán tử splat không chỉ hữu ích cho việc cấu trúc các mảng mà còn để xây dựng chúng.

Trong ví dụ sau, chúng tôi sử dụng splat để nối hai mảng.

[*[1,2], *[3,4]]
=> [1, 2, 3, 4]

Đây tương đương với [[1, 2], [3,4]].flatten .

Nếu đó là kết thúc của câu chuyện, nó sẽ không hữu ích cho lắm. Nhưng splat có một khả năng đặc biệt khác. Nó có thể ép các đối tượng vào mảng một cách thông minh.

# Usually `*thing` wraps `thing` in an array
x = *"hi mom"
# => ["hi mom"]

# ...unless it's nil
x = *nil
# => []

# Arrays are passed through unchanged
x = *[1,2,3]
# => [1, 2, 3]

# But hashes are converted to arrays
x = *{a: 1}
# => [[:a, 1]]

Điều này cung cấp cho chúng tôi một công cụ để xây dựng các mảng mà không cần phải thực hiện hàng tấn cưỡng chế thủ công.

Ví dụ, hãy tưởng tượng bạn đang thu thập một mảng chuỗi cho một số hệ thống cấu hình. Thông thường bạn muốn:

  • Kiểm tra xem mảng có tồn tại hay không và khởi tạo nó nếu không
  • Phản hồi một cách thông minh nếu ai đó cố gắng thêm một mảng chuỗi chứ không chỉ một chuỗi đơn lẻ

Nhà điều hành splat cung cấp cho chúng tôi điều này miễn phí:

# Your configuration hash may or may not have
# an existing :ignore array. 
config = { }

# The callback function might return an array
# or it might return a single item. 

def add_ignores
  "scoundrels" # could also be an array like ["scoundrels", "cads", "ne'er-do-wells"]
end

# This is where the magic happens. No matter what you 
# start with you get an array of things to ignore. 
config[:ignore] = [*config[:ignore], *add_ignores()]

Vậy là xong

Tôi hy vọng rõ ràng là bạn có thể không nên viết lại tất cả mã thao tác mảng hiện có của mình để sử dụng biểu tượng. Chúng không phải lúc nào cũng là công cụ phù hợp và chúng có thể khiến mã khó đọc khi được sử dụng thường xuyên.

Tuy nhiên, đôi khi một thủ thuật mô tả mảng chính xác là những gì bạn cần. Tôi hy vọng, khi thời điểm đó đến, bạn sẽ thử một lần. :)