Rails 这个怎么玩儿?

easonlovewan · 2016年04月11日 · 最后由 u1453357893 回复于 2016年04月12日 · 3455 次阅读

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

递归很简单啊,遇到非 hash 值就打印,hash 值就带着当前 key 开始递归。

#4 楼 @nouse 这个解释赞一个,已经理解了,谢谢

6 楼 已删除

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(',') 吧

@easonlovewan 不可以 join 哦~,join 后得到 string,无法 map

典型的 DFS

LZ,你的主帖中c_d_1目测要改为c_d_4吧...

太麻烦了,你写 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"
需要 登录 后方可回复, 如果你还没有账号请 注册新账号