哈希解构

时间:2013-03-03 21:55:58

标签: ruby hash splat

您可以使用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)

如果不是原生红宝石,Rails是否添加了这样的东西?

目前我正在用

大致做到这一点
foo('arg1', opts.merge(hash1: 'foo'))

4 个答案:

答案 0 :(得分:4)

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

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

答案 1 :(得分:3)

现在是2018年,值得更新。 Ruby 2.0 introduced keyword arguments,还有哈希散列运算符**。现在,您只需执行以下操作即可:

def foo arg1, opts
  [arg1, opts]
end

opts = {hash2: 'bar', hash3: 'baz'}
foo('arg1', hash1: 'foo', **opts)
#=> ["arg1", {:hash1=>"foo", :hash2=>"bar", :hash3=>"baz"}]

答案 2 :(得分:2)

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

class Hash; alias :* :merge end

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

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

我认为最后一个与你想要的完全接近。

答案 3 :(得分:0)

如果您对使用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)