Ruby .store 函数将哈希值从数组更改为单个值
Posted
技术标签:
【中文标题】Ruby .store 函数将哈希值从数组更改为单个值【英文标题】:Ruby .store function changes hash values from array to single value 【发布时间】:2021-04-21 16:08:18 【问题描述】:我正在尝试创建一个哈希,其中键是数字,值是来自两个数组的计数的数组 [0,0]。
我很困惑的是为什么my_hash2.store(x,my_hash2[x][1]+1)
不更新我的计数。
my_hash2 = Hash.new|h,k| h[k] = [0,0]
[12,12,13,14,15,16].each do |x|
my_hash2[x][0] += 1
end
puts my_hash2 # => 12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]
[12,12,13].each do |x|
my_hash2.store(x,my_hash2[x][1]+1)
end
puts my_hash2 # => 12=>1, 13=>1, 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]
puts my_hash2[12][0] #=> 1
puts my_hash2[12][1] #=> 0
【问题讨论】:
当x
等于12
和my_hash2
等于12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]
,my_hash2.store(x,my_hash2[x][1]+1)
--通常写成my_hash2[x] = my_hash2[x][1]+1
--导致my_hash2
的值,对于key 12
从 [2, 0]
更改为 my_hash2[12][1]+1
,等于 0 + 1 #=> 1
。这解释了为什么您会得到不想要的结果。
我猜你可能想要12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0].transform_values |v1,v2| [v1+1, v2+1] #=> 12=>[3, 1], 13=>[2, 1], 14=>[2, 1], 15=>[2, 1], 16=>[2, 1]
。见Hash#transform_values。
您可以将前 4 行替换为 [12,12,13,14,15,16].tally.transform_values |n| [n,0] #12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]
。中间计算是[12,12,13,14,15,16].tally #=> 12=>2, 13=>1, 14=>1, 15=>1, 16=>1
。请参阅Enumerable#tally,它在 Ruby v2.7.0 中首次亮相。
感谢@CarySwoveland 的评论
【参考方案1】:
.store
将 value 给定的 value 与 key 给定的 key 相关联。
(根据文档https://apidock.com/ruby/Hash/store)
因此,这意味着您的密钥存储的任何值都将被新值替换。
my_hash2 = Hash.new|h,k| h[k] = [0,0]
[12,12,13,14,15,16].each do |x|
my_hash2[x][0] += 1
end
puts my_hash2 # => 12=>[2, 0], 13=>[1, 0], 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]
[12,12,13].each do |x|
# in the first run in case of 12 this replaces your [2, 0] with 1 because current value of my_hash2[12][1] is 0 and 0 + 1 is 1
# in the second run we also get 12 but my_hash2[12] is 1 now. and 1[1] equals 0. You are here essentially doing my_hash[12] = 1[1] + 1 = 0 + 1 and it correctly gives you 1
# in the third run it operates on my_hash2[13][1] but same rules apply
my_hash2.store(x,my_hash2[x][1]+1)
end
puts my_hash2 # => 12=>1, 13=>1, 14=>[1, 0], 15=>[1, 0], 16=>[1, 0]
puts my_hash2[12] #=> 1
puts my_hash2[12][0] #=> 1
puts my_hash2[12][1] #=> 0
所以你要么不使用.store
,要么改变这一行:
my_hash2.store(x,my_hash2[x][1]+1)
到:
new_val = [my_hash[x][0], my_hash[x][1]+1]
my_hash2.store(x, new_val)
奇怪的是为什么像1[0]
这样的操作会给你1
而1[1]
会给你0
(并且不会引发任何错误)
答案又在文档中:)
https://ruby-doc.org/core-2.5.0/Integer.html#method-i-5B-5D
int[n] → 0, 1
位引用 - 返回 int 二进制表示中的第 n 位, 其中 int[0] 是最低有效位。
这意味着如果我们将 1 转换为位表示,我们将继续从该表示中获取第 n 位。并且 1 在 0 位置有位,所有其他位置(所以 1,2,3,4...)都是 0。这就是为什么 1[0] 给你 1 但 1[1] 或 1[3] 会给你0。
【讨论】:
以上是关于Ruby .store 函数将哈希值从数组更改为单个值的主要内容,如果未能解决你的问题,请参考以下文章
Vuex store - 将状态中的项目推送到状态数组导致数组中的前一个项目更改为当前状态项目