ruby で hash の入れ子構造体 (hash の value にまた hash があるようなもの) があったときに、 xml でいう xpath 的に要素を指定して操作したいと考えました。例えば要素の削除であるならば、

h = {name:
  {"japanese_first_name" => "太郎",
   "japanese_last_name" => "田中",
   "english_first" => "Taro",
   "english_last" => "Tanaka"
  },
  age: 18
}

del(h, [:name, /japanese/])
# => {:name=>{"english_first"=>"Taro", "english_last"=>"Tanaka"}, :age=>18}

のようなメソッドがあると嬉しいです。 del は、 case (というより、 ===) で比較する、 hash のパスを表します。

この del は、試しに実装してみると、こんな感じになりました。

def del(h, xpath_ish)
  return h.reject {|k,v| xpath_ish.first === k } if xpath_ish.size == 1
  h.map do |k,v|
    new_v = xpath_ish.first === k ? del(v, xpath_ish.drop(1)) : v
    [k, new_v]
  end.to_h
end

ここまでかいてみて、 del を定義したならば、同様に map や reduce, etc などのもろもろの操作を定義したくなります。

ただ、こういった操作は、 ruby を使っていれば、割とよくやりたくなる操作なのではないかと思い、既存のライブラリでこれを実現するものがあるのではないかと考えました。

質問

  • ruby で、 hash に対して、 xpath 的に要素を指定しながら、操作を行うライブラリなどはありますか?
    • 特に、 json を hash で読み込んだ場合などに、このような操作を行いたくなります。