什么是Ruby等效于Python的defaultdict?

时间:2021-07-14 02:59:06

In Python, I can make a hash where each element has a default value when it's first referenced (also know as "autovivification"). Here's an example:

在Python中,我可以创建一个散列,其中每个元素在第一次引用时都有一个默认值(也称为“autovivification”)。这里有一个例子:

from collections import defaultdict
d = defaultdict(int)
d["new_key"] += 1
print d

Printing the dict shows the value for "new_key" is 1.

打印该命令将显示“new_key”的值为1。

What's the equivalent in Ruby? This code throws an error:

在Ruby中,什么是等价的呢?该代码抛出一个错误:

d = {}
d[:new_key] += 1
puts d

test.rb:3:in `<main>': undefined method `+' for nil:NilClass (NoMethodError)

3 个解决方案

#1


10  

You can use the first argument of the Hash.new method for that:

可以使用散列的第一个参数。新方法:

d = Hash.new 0
d[:new_key] += 1
d[:new_key] #=> 1
d[:foo]     #=> 0

Be careful - you might accidentally change the default value:

小心——您可能不小心更改了默认值:

h = Hash.new("Go Fish")
h[:unknown_key]         #=> "Go Fish"
h[:unknown_key].upcase! #=> "GO FISH"
h[:next_key]            #=> "GO FISH"

As "mu is too short" pointed out in his answer, you should better use a proc, as in:

正如“mu is too short”在他的回答中指出,你最好使用proc,如:

h = Hash.new { |h, k| h[k] = 0 }

#2


19  

You can assign a default value using default=:

您可以使用default=:

d.default = 0

Note that this won't really autovivify though, it just makes d[:new_key] return a zero without actually adding a :new_key key. default= can also cause problems if you intend to modify the default value; that means that d.default = [ ] is almost always a mistake as the array will not be copied when the default is accessed.

注意,这并不是真正的autovivify,它只是让d[:new_key]返回一个0,而不添加:new_key键。如果您打算修改默认值,default=也会引起问题;这意味着d.default =[]几乎总是错误的,因为在访问默认值时不会复制数组。

A better choice is usually default_proc=:

更好的选择通常是default_proc=:

d.default_proc = proc { |h, k| h[k] = 0 }

This allows you to have distinct default values and it allows you to add the new key (or not depending on how the proc is structured).

这允许您拥有不同的默认值,并允许您添加新键(或不添加取决于proc的结构)。

You can also set these when creating the Hash:

您还可以在创建散列时设置它们:

d = Hash.new(0)
d = Hash.new { |h, k| h[k] = 0 }

#3


9  

The standard new method for Hash accepts a block. This block is called in the event of trying to access a key in the Hash which does not exist. The block is passed the Hash itself and the key that was requested (the two parameters) and should return the value that should be returned for the requested key.

哈希的标准新方法接受一个块。在试图访问不存在的散列中的键时调用此块。该块通过散列本身和请求的键(两个参数),并且应该返回应该返回的值。

This can be used to create an autovivified hash, among other things:

这可以用来创建一个自动激活的散列,包括:

h = Hash.new{ |h,k| h[k] = 'default value'}

#1


10  

You can use the first argument of the Hash.new method for that:

可以使用散列的第一个参数。新方法:

d = Hash.new 0
d[:new_key] += 1
d[:new_key] #=> 1
d[:foo]     #=> 0

Be careful - you might accidentally change the default value:

小心——您可能不小心更改了默认值:

h = Hash.new("Go Fish")
h[:unknown_key]         #=> "Go Fish"
h[:unknown_key].upcase! #=> "GO FISH"
h[:next_key]            #=> "GO FISH"

As "mu is too short" pointed out in his answer, you should better use a proc, as in:

正如“mu is too short”在他的回答中指出,你最好使用proc,如:

h = Hash.new { |h, k| h[k] = 0 }

#2


19  

You can assign a default value using default=:

您可以使用default=:

d.default = 0

Note that this won't really autovivify though, it just makes d[:new_key] return a zero without actually adding a :new_key key. default= can also cause problems if you intend to modify the default value; that means that d.default = [ ] is almost always a mistake as the array will not be copied when the default is accessed.

注意,这并不是真正的autovivify,它只是让d[:new_key]返回一个0,而不添加:new_key键。如果您打算修改默认值,default=也会引起问题;这意味着d.default =[]几乎总是错误的,因为在访问默认值时不会复制数组。

A better choice is usually default_proc=:

更好的选择通常是default_proc=:

d.default_proc = proc { |h, k| h[k] = 0 }

This allows you to have distinct default values and it allows you to add the new key (or not depending on how the proc is structured).

这允许您拥有不同的默认值,并允许您添加新键(或不添加取决于proc的结构)。

You can also set these when creating the Hash:

您还可以在创建散列时设置它们:

d = Hash.new(0)
d = Hash.new { |h, k| h[k] = 0 }

#3


9  

The standard new method for Hash accepts a block. This block is called in the event of trying to access a key in the Hash which does not exist. The block is passed the Hash itself and the key that was requested (the two parameters) and should return the value that should be returned for the requested key.

哈希的标准新方法接受一个块。在试图访问不存在的散列中的键时调用此块。该块通过散列本身和请求的键(两个参数),并且应该返回应该返回的值。

This can be used to create an autovivified hash, among other things:

这可以用来创建一个自动激活的散列,包括:

h = Hash.new{ |h,k| h[k] = 'default value'}