如果特定键,则哈希深度变换所有值

问题描述 投票:0回答:2

我对社区的尊重! 我有深层嵌套哈希,我想转换所提供的特定键的所有值。像

deep transform values if key == :something
之类的东西 哈希示例:

{:id=>"11ed35b8e53c442ea210c39d6f24bddf",
 :createdAt=>"2022-09-16T12:12:55.454Z",
 :updatedAt=>"2022-09-16T12:12:55.454Z",
 :status=>"ACTIVE",
 :description=>"test",
 :goals=>
  [{:Definitions=>[],
    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
    :status=>"ACTIVE",
    :Definitions=>[{:text=>"Search for relics", :status=>"INACTIVE", :id=>"11ec1fc4bd36f876963867013cee2799"}],
    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
 :healthConcernDefinitions=>[]}

我想转换所有键的所有值

:status
结果必须是:

{:id=>"11ed35b8e53c442ea210c39d6f24bddf",
 :createdAt=>"2022-09-16T12:12:55.454Z",
 :updatedAt=>"2022-09-16T12:12:55.454Z",
 :status=>"TRANSFORMED",
 :description=>"test",
 :goals=>
  [{:Definitions=>[],
    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
    :status=>"TRANSFORMED",
    :Definitions=>[{:text=>"Search for relics", :status=>"TRANSFORMED", :id=>"11ec1fc4bd36f876963867013cee2799"}],
    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
 :healthConcernDefinitions=>[]}

我有几个解决方案 第一个:

hash_to_json = hash.to_json.gsub(/"ACTIVE"|"INACTIVE"/, '"TRANSFORMED"')
JSON.parse(hash_to_json)

第二个:

hash.deep_transform_values { |v| (v == 'ACTIVE' || v == 'INACTIVE') ? 'TRANSFORMED' : v }

两种解决方案都有效,但我不喜欢匹配值,我只想匹配特定的键并在整个哈希中更改它,例如:

hash.deep_transform_keys { |k, v| v = 'TRANSFORMED' if k == :status }

非常感谢!

ruby-on-rails ruby activesupport ruby-hash
2个回答
2
投票

不幸的是,

Hash#deep_transform_values
仅接受块值,而不接受键。不幸的是
Hash#deep_merge
Hash#deep_merge!
没有那么强大

您可以编写自己的方法。这只是想法,你可以改进它

class Hash
  def deep_replace(hash)
    deep_dup.deep_replace!(hash)
  end

  def deep_replace!(hash)
    each_key do |key|
      hash.each do |k, v|
        self[key] = v if key == k
      end

      _replace_object!(self[key], hash)
    end
  end

  private

  def _replace_object!(object, hash)
    case object
    when Hash
      object.deep_replace!(hash)
    when Array
      object.map! { |v| _replace_object!(v, hash) }
    else
      object
    end
  end
end
hash = {:id=>"11ed35b8e53c442ea210c39d6f24bddf",
 :createdAt=>"2022-09-16T12:12:55.454Z",
 :updatedAt=>"2022-09-16T12:12:55.454Z",
 :status=>"ACTIVE",
 :description=>"test",
 :goals=>
  [{:Definitions=>[{:text=>"Search for relics", :status=>"INACTIVE", :id=>"11ec1fc4bd36f876963867013cee2799"}],
    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
    :status=>"ACTIVE",
    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
  :healthConcernDefinitions=>[]}

之后就可以应用了

# Replace one key
hash.deep_replace(status: "TRANSFORMED")

# => {:id=>"11ed35b8e53c442ea210c39d6f24bddf",
# :createdAt=>"2022-09-16T12:12:55.454Z",
# :updatedAt=>"2022-09-16T12:12:55.454Z",
# :status=>"TRANSFORMED",
# :description=>"test",
# :goals=>
#  [{:Definitions=>[{:text=>"Search for relics", :status=>"TRANSFORMED", :id=>"11ec1fc4bd36f876963867013cee2799"}],
#    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
#    :status=>"TRANSFORMED",
#    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
#  :healthConcernDefinitions=>[]}
# Replace few keys
hash.deep_replace(status: "TRANSFORMED", txid: "555", id: "99999999999999999999999999999999")

# => {:id=>"99999999999999999999999999999999",
# :createdAt=>"2022-09-16T12:12:55.454Z",
# :updatedAt=>"2022-09-16T12:12:55.454Z",
# :status=>"TRANSFORMED",
# :description=>"test",
# :goals=>
#  [{:Definitions=>[{:text=>"Search for relics", :status=>"TRANSFORMED", :id=>"99999999999999999999999999999999"}],
#    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
#    :status=>"TRANSFORMED",
#    :id=>"99999999999999999999999999999999"}],
#  :healthConcernDefinitions=>[]}
# Check original (it wasn't changed)
hash

# => {:id=>"11ed35b8e53c442ea210c39d6f24bddf",
# :createdAt=>"2022-09-16T12:12:55.454Z",
# :updatedAt=>"2022-09-16T12:12:55.454Z",
# :status=>"ACTIVE",
# :description=>"test",
# :goals=>
#  [{:Definitions=>[{:text=>"Search for relics", :status=>"INACTIVE", :id=>"11ec1fc4bd36f876963867013cee2799"}],
#    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
#    :status=>"ACTIVE",
#    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
#  :healthConcernDefinitions=>[]}
# Destructive method
hash.deep_replace!(status: "TRANSFORMED", id: "99999999999999999999999999999999")

# => {:id=>"99999999999999999999999999999999",
# :createdAt=>"2022-09-16T12:12:55.454Z",
# :updatedAt=>"2022-09-16T12:12:55.454Z",
# :status=>"TRANSFORMED",
# :description=>"test",
# :goals=>
#  [{:Definitions=>[{:text=>"Search for relics", :status=>"TRANSFORMED", :id=>"99999999999999999999999999999999"}],
#    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
#    :status=>"TRANSFORMED",
#    :id=>"99999999999999999999999999999999"}],
#  :healthConcernDefinitions=>[]}
# Check original (it was changed)
hash

# => {:id=>"99999999999999999999999999999999",
# :createdAt=>"2022-09-16T12:12:55.454Z",
# :updatedAt=>"2022-09-16T12:12:55.454Z",
# :status=>"TRANSFORMED",
# :description=>"test",
# :goals=>
#  [{:Definitions=>[{:text=>"Search for relics", :status=>"TRANSFORMED", :id=>"99999999999999999999999999999999"}],
#    :text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
#    :status=>"TRANSFORMED",
#    :id=>"99999999999999999999999999999999"}],
#  :healthConcernDefinitions=>[]}

1
投票

我们可以使用类似于

deep_transform_keys
的实现来实现密钥的条件覆盖。

def deep_overwrite(object, other_h)
  case object
  when Hash
    object.each_with_object({}) do |(key, value), result|
      result[key] = other_h[key] || deep_overwrite(value, other_h)
    end
  when Array
    object.map { |e| deep_overwrite(e,other_h) }
  else
    object
  end
end

虽然这不采用块格式(如您的帖子中所示),但根据您的用例,这似乎没有必要。相反,这将简单地覆盖原始 (

object
) 中包含的任何键(嵌套在任何级别)的值,该值也包含在
other_h
中。

在您的情况下称之为

original = {:id=>"11ed35b8e53c442ea210c39d6f24bddf",
 :createdAt=>"2022-09-16T12:12:55.454Z",
 :updatedAt=>"2022-09-16T12:12:55.454Z",
 :status=>"ACTIVE",
 :description=>"test",
 :goals=>
  [{:text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
    :status=>"ACTIVE",
    :Definitions=>[{:text=>"Search for relics", :status=>"INACTIVE", :id=>"11ec1fc4bd36f876963867013cee2799"}],
    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
 :healthConcernDefinitions=>[]}

result = deep_overwrite(original,{status: 'TRANSFORMED'})
#=> {:id=>"11ed35b8e53c442ea210c39d6f24bddf",
# :createdAt=>"2022-09-16T12:12:55.454Z",
# :updatedAt=>"2022-09-16T12:12:55.454Z",
# :status=>"TRANSFORMED",
# :description=>"test",
# :goals=>
#  [{:text=>"Follows Action Plan Appropriately, Worse or Warning Symptoms",
#    :status=>"TRANSFORMED",
#    :Definitions=>
#     [{:text=>"Search for relics",
#       :status=>"TRANSFORMED",
#       :id=>"11ec1fc4bd36f876963867013cee2799"}],
#    :id=>"11e818be2f0157329c76634ee23c1d8f"}],
# :healthConcernDefinitions=>[]}
© www.soinside.com 2019 - 2024. All rights reserved.