如何将具有多个子级别项目的哈希转换为非子项目

时间:2016-10-06 08:16:46

标签: ruby-on-rails ruby ruby-on-rails-4

我想将具有多个子级子项的哈希转换为仅哈希一个级别。 例如:

Input:
{"a1"=>{"a11"=>11, "a12"=>12, "a13"=>13, "a14" => {"a141" => 141} }}

Output:
{"a[a11]" => 11, "a[a12]" => 12, "a[a13]" => 13, "a[a14][a141]" => 141}

如何解决上述问题?

3 个答案:

答案 0 :(得分:0)

哈希键可以是任何对象。我首先将新键构建为数组,然后将其转换回字符串:

def convert_keys(in_hash ={})
  in_hash.each_with_object({}) do |(key, value), result|
    if value.is_a?(Hash)
      convert_keys(value).each_pair do |converted_key, converted_value|
        new_key = [ key ] + converted_key
        result[new_key] = converted_value
      end
    else
      result[ [key] ] = value
    end
  end
end

def parse_params(in_hash ={})
  convert_keys(in_hash).each_with_object({}) do |(key, value), result|
    key_postfix = key[1..-1].map { |key_part| "[#{key_part}]" }.join
    str_key =  "#{key[0]}#{key_postfix}"

    result[str_key] = value
  end
end

答案 1 :(得分:0)

接受它:

a = {"a1"=>{"a11"=>11, "a12"=>12, "a13"=>13, "a14" => {"a141" => 141} }}

def modi(hash)
  hash.map do |key, value|
    if value.is_a?(Hash)
      value = modi(value).flatten(1)
      ["[#{key}]" + value.first, value.last]
    else
      ["[#{key}]", value]
    end
  end 
end

def pars(main_hash)
  main_hash.map do |key, value|
    modi(value).each_with_object({}) do |v, res|
      res[v.first.prepend(key.first)] = v.last
    end 
  end.first #*
end 

pars(a)
> {"a[a11]"=>11, "a[a12]"=>12, "a[a13]"=>13, "a[a14][a141]"=>141}

*。或者您可以删除first方法,然后返回:

[{"a[a11]"=>11, "a[a12]"=>12, "a[a13]"=>13, "a[a14][a141]"=>141}]

这可以帮助你,如果将来你会添加一些新的功能,例如,输入将是:`

a = {"a1"=>{"a11"=>11, "a12"=>12, "a13"=>13, "a14"=>{"a141"=>141}}, "b1"=>{"b11"=>11}}

然后,没有first此方法返回:

[{"a[a11]"=>11, "a[a12]"=>12, "a[a13]"=>13, "a[a14][a141]"=>141,{"b[b11]"=>11}]

答案 2 :(得分:0)

如果根据您的输入,您所需的输出是

{"a1[a11]" => 11, "a1[a12]" => 12, "a1[a13]" => 13, "a1[a14][a141]" => 141}

此方法应该有效:

def convert_hash(hash, depth = 0, keys = [], memo = {})
  hash.each do |key, value|
    keys = keys.first(depth) << key
    if value.is_a? Hash
      convert_hash(value, depth + 1, keys, memo)
    else
      head, *tail = keys
      # if there was no typo in your question, then use `head.first` here
      converted_key = tail.reduce(head) { |memo, key| "#{memo}[#{key}]"}
      memo[converted_key] = value
    end
  end
  memo
end

(pry)> convert_hash({"a1"=>{"a11"=>11, "a12"=>12, "a13"=>13, "a14"=>{"a141"=>141}}})
 => {"a1[a11]"=>11, "a1[a12]"=>12, "a1[a13]"=>13, "a1[a14][a141]"=>141}