2016-06-23 14 views
0

私はスタンフォードCoreNLPを使って(フランス語または英語の)文章の基本的な依存関係を解析します。それは私にこのような文字列の結果を与える:スタンフォードコアnlpのタグ付き文字列をハッシュにパースするRuby

「(ROOT(SENT(NP(DET CE)(NCマガシン))(VN(V estは))(AP(ADJポプリ))(COORD(CCのMAIS) (シント(NP(DETレ)(ADJ vendeuses))(VN(Vのsont))(AP(ADJgéniales))))(PUNC!)))」

今、私はこれを解析する結果必要がありますルビーのハッシュや構造体、jsonなどで簡単に操作できます。例えば

はハッシュで:

{'ROOT'=>{'SENT'=>{'NP'=>{'DET'=>'Ce'},'NC'=>'Magasin'}etc...}} 

私はそれが、無成功を行うには、いくつかの方法を試してみました。 これを達成するためのアドバイスや例を教えてください。構造がよく形成されているので、我々はそれに依存しており、私たち自身の小さなパーサを構築することができ

おかげ

+1

お試しいただいた内容を表示できますか?私たちはあなたが試したことで問題を解決することができるかもしれません。 –

+0

"[ask]"とリンク先のページをお読みください。問題を解決するためのあなたの努力の証拠を見る必要があります。あなたはいくつかの方法を試したと言いますから、そのコードを最小限にまとめて、それを見せてください。それ以外の場合、Stack Overflowの仕組みではないコードを書くようにしているようです。コードに問題があるので、「[mcve]」を読むことをお勧めします。あなたは "ruby corenlp"を検索してその結果を試しましたか? –

答えて

0

はここで本当に簡単パーサの実装です。 tokenizeは文字列を部分に分割し、parseはトークンを式にグループ化し、それらをhasherizeにフィードし、それらをツリーに変換します。

def tokenize(str) 
    str.split(/\s+|([()])/).reject(&:empty?) 
end 

def hasherize(tokens) 
    tokens, hsh = tokens.dup, {} 

    while expr = tokens.shift 
    _, key, val = expr 

    if val 
     hsh[key] = val 
    elsif key 
     tokens, hsh[key] = hasherize(tokens) 
    else break 
    end 
    end 

    [ tokens, hsh ] 
end 


def parse(str) 
    tokens = tokenize(str) 
    .slice_when {|left,right| left == ")" || right == "(" } 
    hasherize(tokens.to_a)[1] 
end 

str = "(ROOT (SENT (NP (DET Ce) (NC magasin)) (VN (V est)) (AP (ADJ pourri)) (COORD (CC mais) (Sint (NP (DET les) (ADJ vendeuses)) (VN (V sont)) (AP (ADJ géniales)))) (PUNC !)))" 
p parse(str) 
# => { "ROOT" => { 
#  "SENT" => { 
#   "NP" => { "DET" => "Ce", "NC" => "magasin" }, 
#   "VN" => { "V" => "est" }, 
#   "AP" => { "ADJ" => "pourri" }, 
#   "COORD" => { 
#   "CC" => "mais", 
#   "Sint" => { 
#    "NP" => { "DET" => "les", "ADJ" => "vendeuses" }, 
#    "VN" => { "V" => "sont" }, 
#    "AP" => { "ADJ" => "géniales" } 
#   } 
#   }, 
#   "PUNC" => "!" 
#  } 
#  } 
# } 
+0

完全に動作します。 私はこのようなアプローチをしないでください。私の最初の試みは文字で文字を検査し、 '('と ')'を扱うことでしたが、コードはすぐに判読できなくなり、より速く安全な方法があることが分かりました。 – youwan

0

。最初に) (をカンマに変更し、カッコをカスケードに変更してハッシュを作成し、最後のステップではトークンとみなして残りのすべてを引用します。

eval str.gsub(/\)\s\(/, ',') 
     .gsub(/[()\s]/, '(' => '{', ')'=>'}', ' ' => '=>') 
     .gsub(/[^{}=> ",]+/) { |m| %Q|"#{m}"| } 

#⇒ {"ROOT"=> 
# {"SENT"=> 
#  {"NP"=>{"DET"=>"Ce", "NC"=>"magasin"}, 
#  "VN"=>{"V"=>"est"}, 
#  "AP"=>{"ADJ"=>"pourri"}, 
#  "COORD"=>{"CC"=>"mais", 
#     "Sint"=>{"NP"=>{"DET"=>"les", "ADJ"=>"vendeuses"}, 
#       "VN"=>{"V"=>"sont"}, 
#       "AP"=>{"ADJ"=>"géniales"}}}, 
# "PUNC"=>"!"}}} 

私はevalためdownvoting、コメントで観客を期待していますが、入力を生産しているが、それは絶対に大丈夫です。

より安全なオプションは、しかし、JSON.parseに次のようになります。

JSON.parse str.gsub(/\)\s\(/, ',') 
       .gsub(/[()\s]/, '(' => '{', ')'=>'}', ' ' => ':') 
       .gsub(/[^{}:=> ",]+/) { |m| %Q|"#{m}"| } 
+0

私はこれが編集であることを認識しましたが、より安全なオプションを回答の先頭に置くことを検討するべきかもしれません。これが何をしているのかを正確に説明することも役立ちます。非常に少数の人々が正規表現に慣れていません。 –

+0

@JustinWoodいいえ、ここでは 'JSON'を使うのは意味的に間違っています。 'eval'は、この入力がエイリアンのソースから来ない限り、はるかに良くフィットします。この場合にのみ、後者が使用される。 – mudasobwa

+0

@mudasobwaどのようにしてこの文字列をJSONに "変換"し、それをRubyに変換して解析するよりも "意味的に間違っている"どちらもクルージュです。どちらも仕事を終わらせる。一つは他のものよりも安全です。 –

関連する問題