为啥在合并另一个哈希时会更新嵌套哈希的所有值?

Posted

技术标签:

【中文标题】为啥在合并另一个哈希时会更新嵌套哈希的所有值?【英文标题】:Why all values of a nested hash are updated when merging another hash?为什么在合并另一个哈希时会更新嵌套哈希的所有值? 【发布时间】:2022-01-08 03:57:37 【问题描述】:

我有以下哈希:

hash = 2021=>:gastosCompra=>0, 2022=>:gastosCompra=>0, 2023=>:gastosCompra=>0

如下创建

headers = 
  gastosCompra: 'gastos compra',


elements = headers.inject()  |h, (k, _v)| h[k] = 0; h 

hash = Hash[years.collect  |item| [item, elements] ]

我正在尝试更新 gastosComprakey year 2021。我试过mergedeep_merge,但不幸的是所有其他键也都更新了:

hash[year][:gastosCompra] = 555
hash[year].merge!(gastosCompra: 555)
hash[year].deep_merge!(gastosCompra: 555)

这是结果:

hash = 2021=>:gastosCompra=>555, 2022=>:gastosCompra=>555, 2023=>:gastosCompra=>555

如果我只想更新 2021 年,为什么要更新所有嵌套的哈希?我想我可以遍历键并在找到 2021 年时停止,但我想避免这种情况。

【问题讨论】:

我敢打赌,所有的值实际上都是同一个对象。检查hash.values.map(&:object_id)。如果都一样,请告诉我们你是如何生成哈希的 您为什么要使用多年未维护的 Ruby on Rails 版本?另外,这与 Ruby on Rails 有什么关系? 抱歉,标签错误。 是的,所有对象都具有相同的对象 ID。问题不在更新时,而是在创建时 问题在这里Hash[years.collect |item| [item, elements] ]。我最终循环并为嵌套哈希创建了新对象。不错的选择,非常感谢您指出@BroiSatse 【参考方案1】:

所有的对象ID都相同,你必须复制你的elements哈希。

它们都指向同一个地址。

在 ruby​​ 中有蜡黄的副本:

Object#dup : https://ruby-doc.org/core-3.0.3/Object.html#method-i-dup

hash = Hash[years.collect |item| [item, elements.dup] ]

Kernel#clone : https://ruby-doc.org/core-3.0.3/Kernel.html#method-i-clone

您也可以使用 ActiveSupport 进行深层复制:https://api.rubyonrails.org/classes/Hash.html#method-i-deep_dup

仅供参考 -> 请参阅 Ruby Marshal 类,它在某些情况下很有用:https://ruby-doc.org/core-3.0.3/Marshal.html

【讨论】:

以上是关于为啥在合并另一个哈希时会更新嵌套哈希的所有值?的主要内容,如果未能解决你的问题,请参考以下文章

Perl 嵌套哈希匹配和合并

访问和更新哈希值 Ruby

MongoDB 哈希索引

虽然哈希值不同,但为啥我的对象存储在同一个位置?

数据库(比如MYSQL) ,表连结查询与子查询哪个效率高些? 为啥

Perl如何访问作为另一个哈希值的数组元素的哈希?