Ruby中哈希的等价物是JavaScript的对象初始化器ES6简写。

20

在JavaScript ES6中,我们可以像这样创建变量名称成为键的对象:

> let a = 'aaa'
'aaa'

> let b = 'bbb'
'bbb'

> { a, b }
{ a:"aaa", b:"bbb" }

Ruby有没有类似于哈希表的东西?

澄清: 显然,这个问题涉及到简写符号。我在寻找的是{a,b}而不是{a:a,b:b}

6个回答

23

16
我希望有,不过... :) - Louis St-Amour
1
其实没什么难理解的:如果你看到一个对象没有常规的键值语法,那么它就是简写形式——这是一个有用的功能,它试图让你在移动数据时使用一致的名称。 - funder7

6

简短回答 不行。

详细回答

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选择修补过的Ruby版本:
rvm use 2.5.0-imphash

(Imphash是implicit hash的缩写)

2

此功能未集成到该语言中。不过,您对此有何看法?

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}

唯一的缺点是您需要传递绑定才能访问本地变量。


1

1
从 Ruby 3.1 开始,可以这样做:
x = 1
y = 2

{x:, y:}
# => {:x=>1, :y=>2}

函数的参数也可以被省略:

def x
  1
end

def y
  2
end

{x:, y:}
# => {:x=>1, :y=>2}

游乐场


1
虽然 Ruby / Rails 还不支持 ES6 中哈希的简写语法,但已经有一些方便的惯用语可以使用。

Ruby

考虑以下方法:
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

以上内容加上一些额外的方法对于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]"


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接