在JavaScript ES6中,我们可以像这样创建变量名称成为键的对象:
> let a = 'aaa'
'aaa'
> let b = 'bbb'
'bbb'
> { a, b }
{ a:"aaa", b:"bbb" }
Ruby有没有类似于哈希表的东西?
澄清:
显然,这个问题涉及到简写符号。我在寻找的是{a,b}
而不是{a:a,b:b}
。
在JavaScript ES6中,我们可以像这样创建变量名称成为键的对象:
> let a = 'aaa'
'aaa'
> let b = 'bbb'
'bbb'
> { a, b }
{ a:"aaa", b:"bbb" }
Ruby有没有类似于哈希表的东西?
澄清:
显然,这个问题涉及到简写符号。我在寻找的是{a,b}
而不是{a:a,b:b}
。
更新:将在3.1中实现。 https://bugs.ruby-lang.org/issues/14579#note-14
不,没有这样的简写符号。
被拒绝了。我看过JavaScript的新语法,但我并不喜欢。它并没有让任何事情更易懂。
Matz。
简短回答 不行。
详细回答
2015年,前田修吾提出了一个补丁来解决这个问题(您可以在此处阅读有关此问题的详细信息:https://bugs.ruby-lang.org/issues/11105)。
当时,Matz并不支持这个想法,但他可能会在未来改变主意。
同时 - 您可以利用Shugo的补丁并自己打补丁版本的Ruby以拥有ES6哈希字面量!
要打补丁Ruby以添加哈希,请执行以下操作:
1)从此处下载补丁https://gist.github.com/thechrisoshow/1bb5708933d71e0e66a29c03cd31dcc3(目前适用于Ruby 2.5.0)
2)使用RVM安装已打补丁的Ruby版本。例如:
rvm install 2.5.0 -n imphash --patch imphash.patch
rvm use 2.5.0-imphash
此功能未集成到该语言中。不过,您对此有何看法?
https://gist.github.com/smtlaissezfaire/e81356c390ae7c7d38d435ead1ce58d2
def hash_shorthand(source_binding, *symbols)
hash = {}
symbols.each do |symbol|
hash[symbol] = source_binding.local_variable_get(symbol)
end
hash
end
$ irb -r './hash_shorthand.rb'
>> x = 10
>> y = 20
>>
>> puts hash_shorthand(binding, :x, :y)
{:x=>10, :y=>20}
唯一的缺点是您需要传递绑定才能访问本地变量。
x = 1
y = 2
{x:, y:}
# => {:x=>1, :y=>2}
函数的参数也可以被省略:
def x
1
end
def y
2
end
{x:, y:}
# => {:x=>1, :y=>2}
def test_splat(a:, b:, c:)
[a, b, c].inspect
end
test_splat(a: 4, b: 5, c: 6)
产生 "[4, 5, 6]"
如果您已经有一个哈希表,例如hash = { a: 1, b: 2, c: 3 }
,那么您可以直接这样调用:
test_splat(hash)
产生 "[1, 2, 3]"
如果您有一个子哈希表,您可以使用关键字扩展运算符**
与其他关键字参数一起使用。例如,如果您有sub_hash = { a: 1, b: 2 }
,调用:
test_splat(sub_hash)
会产生 ArgumentError: missing keyword: c
并且调用:
test_splat(sub_hash, c: 3)
会产生 ArgumentError: wrong number of arguments (given 1, expected 0)
但是使用扩展运算符**
,您可以扩展sub_hash
参数:
test_splat(**sub_hash, c: 3)
将产生 "[1, 2, 3]"
更多阅读请参见https://www.justinweiss.com/articles/fun-with-keyword-arguments/
以上内容加上一些额外的方法对于Rails用户来说非常方便,特别是在控制器中传递参数时。
假设你有一个ActionController::Parameters
对象,它具有比你需要的更多的属性,而你只想要一个子集。例如:{ a: 1, b: 2, d: 4 }
。在这种情况下,Hash
上的slice
方法非常方便。
首先,允许您的参数:
permitted_params = params.permit(:a, :b, :d).to_h.symbolize_keys
。
.to_h.symbolize_keys
,因为ActionController::Parameters
不支持symbolize_keys
,而kwargs需要args的键是符号,而不是字符串。所以.to_h
将其转换为ActiveSupport :: HashWithIndifferentAccess
,而symbolize_keys
将哈希的键从字符串转换为符号。
现在,调用:
test_splat(**permitted_params, c: 3)
会产生ArgumentError:unknown keyword: d
,因为d
不是test_splat
方法的kwarg。虽然使用slice实现了我们在这里想要的:
test_splat(**permitted_params.slice(:a, :b), c: 3)
产生"[1, 2, 3]"