hash 转字符串这个用递归怎么实现?
{a: 1, b:2, c:{d:4, e:5}} --> "a_1,b_2,c_d_1,c_e_5"
def to_str hash
strs = []
hash.each do |key, value|
if value.is_a? Hash
strs += to_str(value).map {|s| "#{key}_#{s}"}
else
strs << "#{key}_#{value}"
end
end
strs
end
#1 楼 @piecehealth 补充一下:
def to_str hash
strs = []
hash.each do |key, value|
if value.is_a? Hash
strs += to_str(value).map {|s| "#{key}_#{s}"}
else
strs << "#{key}_#{value}"
end
end
strs.join(",")
end
nested hash key 转成数组:
def flat_hash(obj, k = [])
return {k => obj} unless obj.is_a?(Hash)
obj.inject({}) { |h, v| h.merge! flat_hash(v[-1], k + [v[0]]) }
end
hash = {a: 1, b: 2, c: {d: 4, e: 5}}
flat_hash(hash)
=> {[:a]=>1, [:b]=>2, [:c, :d]=>4, [:c, :e]=>5}
nested hash key value 拼接:
def flat_hash(obj, k = [])
obj.is_a?(Hash) ? obj.inject([]) { |h, v| h += flat_hash(v[-1], k + [v[0]]) } : [[k + [obj]].join('_')]
end
hash = {a: 1, b: 2, c: {d: 4, e: 5}}
flat_hash(hash)
=> ["a_1", "b_2", "c_d_4", "c_e_5"]
剩下一步,自己 x.join(',') 吧
太麻烦了,你写 hash 的时候已经递归好了,只要用宏就可以了
def build(hash)
hash.map{|k,v| [v].flatten.map{|x| "#{k}_#{x}"}}
end
hsh = {a: 1, b: 2, c: {d: 4, e: 5}}
p (eval hsh.to_s.gsub(/\{/, 'build({').gsub(/\}/, '})')).flatten.join(',')
原理:{a: 1, b: 2, c: {d: 4, e: 5}}
转为 "build({:a=>1, :b=>2, :c=>build({:d=>4, :e=>5})})"
直接 eval
hash = {a: 1, b: 2, c: {d: 4, e: 5}}
URI.unescape(hash.to_query).gsub('=', '_').gsub('&', ',').gsub('[', '_').gsub(']', '')
"a_1,b_2,c_d_4,c_e_5"