如何动态调用将数组作为参数的方法?

时间:2012-02-21 21:30:43

标签: ruby-on-rails ruby ruby-on-rails-3

我的方法如下:

def method (a=[],b=[])
 ...
end

我用这样的变量调用这个方法:

method(h[0].values_at("value"), h[1].values_at("value")) 

其中h[0]h[1]是哈希值。它工作正常。

我不知道在下一次运行中h[1]是否会出现在那里,所以如果哈希h[1]不存在则会给我错误。

如何修改它以便根据h[0]h[1]是否存在动态调用,并使用正确数量的参数调用方法。

4 个答案:

答案 0 :(得分:1)

完全按照你的要求做最简单的方法是:

if h[1]
  method(h[0].values_at("x"), h[1].values_at("x"))
else
  method(h[0].values_at("x"))
end

另一个想法是在h [1]为nil

的情况下放置默认哈希
method(h[0].values_at("x"), (h[1]||{}).values_at("x") )

如果你确定h永远不会有超过2项,你可以这样做:

method *(h.map{|i|i.values_at("x")})

答案 1 :(得分:1)

希望我理解你的问题:

method(h[0].values_at("value"), 
        h[1] ? h[1].values_at("value") : []
      ) 

您的问题:如果h[1]不存在,h[1].values_at将引发异常。因此,如果值可用,则必须先测试。在上面的代码片段中,我使用了三元运算符。

扩展版本将是:

par2 = []
par2 = h[1].values_at("value") if h[1]

method(h[0].values_at("value"), 
        par2
      ) 

使用我的解决方案,您不需要方法定义中的默认值。


在你的评论中,你扩展了你的问题。

使用四个参数可以像这样使用它:

def method(p1,p2,p3,p4)
  #...
end

method(
    h[0] ? h[0].values_at("value") : [],
    h[1] ? h[1].values_at("value") : [],
    h[2] ? h[2].values_at("value") : [],
    h[3] ? h[3].values_at("value") : [],
  ) 

但我会推荐更通用的版本:

def method(*pars)
  #pars is an Array with all values (including empty arrays.
  #The next check make only sense, if you need exactly 4 values.
  raise "Expected 4 values, get #{pars.size}"  unless pars.size == 4
end

method( *(h.map{|i|i.values_at("x")})

另一个 - 可能不太好 - 想法:

如果h[1]没有此元素,则将{n}(h的结果)扩展为为值_at返回[]

class NilClass  
  def values_at(x)
    []
  end
end

答案 2 :(得分:0)

如果您使用Ruby On Rails,则可以执行try方法:

method(h[0].values_at("value"), h[1].try(:values_at, 'value') || [])

方法try的示例:

nil.try('[]', :x) # => nil
{:x => 't'}.try('[]', :x) # => 't'

答案 3 :(得分:0)

您可以更改函数签名以接受变量参数。

def foo(*args)
  options = args.extract_options!
  p options
  p args 
end
  • 不带参数的调用

    foo()
    {}
    []
    
  • 使用2个参数进行调用

    foo(1, 2)
    {}
    [1, 2]
    
  • 使用3个参数进行调用

    foo(1, 2, 3)
    {}
    [1, 2, 3]
    
  • 使用3个参数和选项哈希

    进行调用
    foo(1, 2, 3, :debug => true)
    {:debug=>true}
    [1, 2, 3]