6

您可以使用 splat 运算符解构数组。

def foo(arg1, arg2, arg3)
  #...Do Stuff...
end
array = ['arg2', 'arg3']
foo('arg1', *array)

但是有没有办法为了选项类型的优点而破坏哈希?

def foo(arg1, opts)
  #...Do Stuff with an opts hash...
end
opts = {hash2: 'bar', hash3: 'baz'}
foo('arg1', hash1: 'foo', *opts)

如果不是原生 ruby​​,Rails 是否添加了类似的东西?

目前我正在做这个大致

foo('arg1', opts.merge(hash1: 'foo'))
4

4 回答 4

6

是的,有一种方法可以解构散列:

def f *args; args; end
opts = {hash2: 'bar', hash3: 'baz'}
f *opts  #=> [[:hash2, "bar"], [:hash3, "baz"]]

问题是你想要的实际上根本不是解构。你试图从

'arg1', { hash2: 'bar', hash3: 'baz' }, { hash1: 'foo' }

(请记住,这'arg1', foo: 'bar'只是 的简写'arg1', { foo: 'bar' }

'arg1', { hash1: 'foo', hash2: 'bar', hash3: 'baz' }

根据定义,这就是合并(注意周围的结构 - 哈希 - 仍然存在)。而解构从

'arg1', [1, 2, 3]

'arg1', 1, 2, 3
于 2013-03-03T22:39:48.187 回答
5

现在是 2018 年,这值得更新。Ruby 2.0 引入了关键字参数以及 hash splat 运算符**。现在您可以简单地执行以下操作:

def foo(arg1, opts)
  [arg1, opts]
end

opts = {hash2: 'bar', hash3: 'baz'}
foo('arg1', hash1: 'foo', **opts)
#=> ["arg1", {:hash1=>"foo", :hash2=>"bar", :hash3=>"baz"}]
于 2018-08-10T18:07:59.120 回答
3

没有这样的事情(尽管已经提出)。由于这会改变解析规则,它不能在 Ruby 中实现。我能想到的最好的方法是*在哈希上定义

class Hash; alias :* :merge end

并以下列方式之一使用它:

foo('arg1', {hash1: 'foo'}*opts)
foo('arg1', {hash1: 'foo'} *opts)
foo('arg1', {hash1: 'foo'}. *opts)

我认为最后一个与您想要的相当接近。

于 2013-03-03T22:35:23.820 回答
1

如果您可以使用 active_support:

require 'active_support/core_ext/hash/slice.rb'

def foo(*args)
  puts "ARGS: #{args}"
end

opts = {hash2: 'bar', hash3: 'baz'}
foo *opts.slice(:hash2, :hash3).values

...或者您可以修改自己的解决方案:

class Hash
  def pluck(*keys)
    keys.map {|k| self[k] }
  end
end

def foo(*args)
  puts "ARGS: #{args}"
end

opts = {hash2: 'bar', hash3: 'baz'}
foo *opts.pluck(:hash2, :hash3)
于 2014-09-14T01:37:50.647 回答