2012-02-28 44 views
9

Tôi có một loạt hàm trong một mảng đối tượng hoặc một đối tượng được thiết kế để xử lý như một mảng chứa một đối tượng và tôi đang tìm kiếm một cách sạch hơn để thực hiện điều này. Về cơ bản, tôi muốn biết làm thế nào tôi có thể làm cho một phần unless trong hàm sau ngắn gọn hơn:Chấp nhận tham số dưới dạng đối tượng riêng lẻ hoặc dưới dạng mảng đối tượng

def foo(bar_or_bars) 
    unless bar_or_bars.is_a?(Array) 
    bar_or_bars = [bar_or_bars] 
    end 
    bar_or_bars.each { |baz| ... } 
end 

Bất kỳ trợ giúp sẽ được đánh giá cao! Cảm ơn.

Trả lời

11

Điều đầu tiên bạn có thể làm là viết logic unless trong một dòng duy nhất:

bars = bar_or_bars.is_a?(Array) ? bar_or_bars : [bar_or_bars] 

Như bạn thấy đấy, tôi cung cấp cho nó một cái tên mới ở đây, vì nó không còn là một quán bar hoặc quán bar, nó bây giờ chắc chắn là một bộ sưu tập.

Vấn đề với điều này và cách tiếp cận ban đầu của bạn là mặc dù chức năng của bạn có thể hoạt động trên bất kỳ Enumerable, bạn sẽ buộc người dùng của bạn cung cấp cho bạn một đối số của một loại cụ thể.

Một lừa gọn gàng để giải quyết một phần vấn đề đó là những điều sau:

def foo(bar_or_bars) 
    bars = [*bar_or_bars] 
    bars.each { |baz| ... } 
end 

tôi sẽ không chính xác gọi đó là có thể đọc được, mặc dù. Nó thực sự có mùi giống như thiết kế API xấu. Có lẽ bạn nên tham gia tốt hơn nhiều tranh cãi như thế này:

def foo(*bars) 
    bars.each { |baz| ... } 
end 

Và để cho người gọi quyết định xem anh ta muốn vượt qua một đối tượng duy nhất hoặc một mảng:

foo("XYZ") 
ary = ["abc", "def"] 
foo(*ary) 
+0

Cảm ơn, mà lừa thứ hai là những gì tôi đang tìm kiếm. Tôi biết nó không lý tưởng, nhưng tôi thực sự quá đơn giản: vì tôi có nhiều tham số liên tiếp giống như tôi đã mô tả, tôi không thể chỉ sử dụng biểu tượng đồng bằng cũ trong danh sách tham số. – user2398029

18

Giải pháp sạch nhất tôi đã tìm thấy được bằng cách sử dụng phương pháp kernel Array:

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

nên

def foo(bar_or_bars) 
    bars = Array(bar_or_bars) 
    bars.each { |baz| ... } 

Điều này thậm chí sẽ làm việc trên mảng lồng nhau có mảng như các yếu tố (họ sẽ không được làm phẳng ra)

1

Tôi hiện đang sử dụng này:

bars = [bar_or_bars].flatten 
Các vấn đề liên quan