2012-02-28 134 views
9

我有一大堆函數可以接受一個對象數組,或者一個對象被設計爲一個包含一個對象的數組,我正在尋找一個更清潔的方式來實現這一點基本上,我想知道我怎麼能做出unless部分在以下功能更簡潔:接受作爲單個對象或對象數組的參數

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 

任何幫助將不勝感激!謝謝。

回答

11

你可以做的第一件事就是寫unless邏輯一行:

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

正如你看到的,我給它一個新的名字在這裏,因爲它不再是一個或多個杆,它現在絕對是一個集合。

這和你原來的方法的問題是,雖然你的功能可以在任何Enumerable工作,你會強迫你的用戶給你一個特定類型的參數,這打破了鴨子打字。

一個絕招來部分地解決這個問題是這樣的:

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

我不完全稱之爲可讀,雖然。它實際上聞起來很像糟糕的API設計。也許你應該更好地利用多個參數是這樣的:

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

而讓來電者決定是否要通過單個對象或數組:

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

謝謝,第二招是我一直在尋找。我知道它並不理想,但實際上我已經簡化了一些:因爲我有許多連續的參數,其行爲與我描述的相似,所以我無法在參數列表中使用普通的舊splat。 – user2398029 2012-02-28 03:20:54

18

我發現是使用最簡潔的解決方案內核方法陣列:

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

所以

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

這甚至會在具有數組作爲元素嵌套數組工作

1

我目前使用這個(他們不會變平):

bars = [bar_or_bars].flatten 
相關問題