Crystal - 如何递归更改哈希值并将每个更改保存到新哈希

时间:2018-02-14 11:12:55

标签: crystal-lang

使用此Hash对象

{"foo" => {"bar" => 1, "baz" => 2}, "bla" => [1,2,3]}

我想生成这个哈希对象数组

[
  {"foo" => "*", "bla" => [1,2,3]},
  {"foo" => {"bar" => "*", "baz" => 2}, "bla" => [1,2,3]},
  {"foo" => {"bar" => "1", "baz" => "*"}, "bla" => [1,2,3]},
  {"foo" => {"bar" => "*", "baz" => 2}, "bla" => "*"}, 
]

我基本上把每个密钥都改为" *"同时保留哈希的整体结构并保存在某个数组中生成的新哈希。

我已经尝试了很多想法,但大多数只是不会工作,因为我之前可以猜测Array类型,我只知道这个哈希是由JSON.parse生成然后变成Hash(String,JSON :: Any)

我目前正在尝试

hash = {"bar" => {"and" => "2", "br" => "1"}}
arr = [hash, {"bar" => "1"}]
arr.delete(arr.last)
arr.delete(hash)

def changer(hash, arr, original = nil)
  original = hash.dup
  hash.each do |k, v|
    if v.is_a?(Hash)
       changer(v, arr, hash)
    elsif v.is_a?(Array)
      v.each do |a|
        if a.is_a?(Hash)
            changer(a, arr, hash)
        end  
        end
  elsif v.is_a?(String) && original.is_a?(Hash(String, String))
      original[k.to_s] = "*"
      arr << original
    end
  end
end

1 个答案:

答案 0 :(得分:5)

Crystal v0.25.0 implements JSON::Any and YAML::Any without recursive aliases。随着这种变化:

require "json"

hash = JSON.parse(%(
  {"foo": {"bar": 1, "baz": 2}, "bla": [1,2,3]}
))

def changer(any : JSON::Any)
  result = [JSON::Any.new("*")]
  if (hash = any.as_h?)
    hash.each do |key, value|
      changer(value).each do |s|
        result << JSON::Any.new(hash.merge({key => s}))
      end
    end
  end
  result
end

puts changer(hash).join("\n")
*
{"foo" => "*", "bla" => [1_i64, 2_i64, 3_i64]}
{"foo" => {"bar" => "*", "baz" => 2_i64}, "bla" => [1_i64, 2_i64, 3_i64]}
{"foo" => {"bar" => 1_i64, "baz" => "*"}, "bla" => [1_i64, 2_i64, 3_i64]}
{"foo" => {"bar" => 1_i64, "baz" => 2_i64}, "bla" => "*"}