Ruby哈希表初始化(默认值为nil)

14

我一直在阅读Ruby文档,并查看其他帖子上的问题,但我仍然对此有疑问:

#counts each number in an array once
array = [1,1,2,5,3,2,5,3,3,3]
numbers = {}
array.each { |num| numbers[num] += 1 }

=> in `block in mode': undefined method `+' for nil:NilClass (NoMethodError)
Hash 文档 中,Hash 的默认值为 nil,这就是我假设出现此错误的原因。是否有更好的方法将每个键/(值 += 1) 插入到 numbers 数组中?

假设您执行了 numbers = Hash.new(0),然后在 num 不是哈希键时执行 numbers[num] += 1。由于在创建哈希时给定了默认值 0,当 Ruby 发现 num 不是哈希键时,它会创建一个新的哈希元素 h[num] = 0。然后它执行 h[num] += 1 # => 1,就完成了。 - Cary Swoveland
谢谢,现在更加清晰了。 - oconn
如果你在想,当new有一个默认参数时,Ruby只有在执行赋值操作时才会创建哈希元素。例如,如果 h = Hash.new(0),那么在if语句if h[6] == 0中,h[6]将等于nil,导致条件为假,并且不会创建键为6的哈希元素(否则会导致if条件为真)。 - Cary Swoveland
4个回答

30

尝试将默认值作为新哈希的参数传递

numbers = Hash.new(0)

2
您也可以明确地这样做:
array.each { |num| numbers[num] = (numbers[num] || 0) + 1 }

2

使用injectHash.new(0)的变体

  numbers = [1,1,2,5,3,2,5,3,3,3].inject(Hash.new(0)){|numbers, number| numbers[number] +=1; numbers}

1
除了使用Hash默认值外,您还可以尝试使用group_by来处理:
array = [1,1,2,5,3,2,5,3,3,3]
numbers = Hash[*array.group_by { |i| i }.flat_map { |k, v| [k , v.size] }]

如果你多试试,可能会有更好的方法。


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