比如实现:
data = {name: 'haha', info: {address: 'xx'}, admin: {password: 'xxxx'}} data.select(|k, v| k == :password) == 'xxxx' data.modify{|k, v| if k == :password ? 'filtered' : v }
操作树状的 Hash 结构。
没有吧,因为 k 在树的各个节点都可以相同,这样库的行为很难去定义了或者定义就很复杂了。
class Hash def modify(&block) map { |k, v| v.is_a?(Hash) ? v.modify(&block) : yield(k, v) } end end data = {name: 'haha', info: {address: 'xx'}, admin: {password: 'xxxx'}} puts data.modify {|k, v| k == :password ? 'filtered' : v }
你那两个例子就没一个能正确的。。太坑了。
最后还是自己写了一个简单的拓展:
class Hash # filter nested hash value by specific key # Example: # {a: {b: 12}}.nested_filter(:b, 0) == {a: {b: 0}} def nested_filter(key, value) self.nested_modify do |k, v| v = value if k == key [k, v] end end # modify nested hash value # Example: # {a: {b: 12}}.nested_modify{ |k, v| [:"#{k}1", v]} == {a1: {b1: 12}} def nested_modify(&block) result = self.map do |k, v| v = v.nested_modify(&block) if v.kind_of?(Hash) block.call(k, v) end Hash[result] end end
首先,作为一个 Hash 你一般需要知道可能存在的 key。 如果 key 和 value 都是未知的,hash 的结构也是未知,那么不如用其他数据结构,比如 xml。 hash 的意义就是根据已知的 key 快速得到 value,如果你这边写了一个搜索方法,那么一开始用 hash 就不合适。
如果想快速得到某个嵌套 hash 的 value,可以用下面方法
class Hash def g(*args) child = self.send :[], args.shift if child if args.empty? child else child.g(*args) end else nil end end end # {:user => # {:post_ids => [1,2,3]} # } Array(params.g(:user, :post_ids))
当你想用一个很复杂嵌套的 Hash 的时候,很有可能更好的方案是把这样的复杂数据封装成对象,这样即使针对深层数据的操作也可以提到表面上来。
http://solnic.eu/2012/06/25/get-rid-of-that-code-smell-primitive-obsession.html