2017-06-14 2 views
0

私はNatural Language Processingプロジェクト(およびElixirの学習)に取り組んでおり、データを変換する慣用的な方法を理解することはできません。縮小/折りたたみ時のデータ構造の作成

ドメイン内の細かい部分であなたを退屈させないために、問題をアドレスの解析に転記してみましょう。彼らは他の人を残したままその場でデータ構造を構成するために、関連するトークンを使用して、文字列トークンのリストを考えると

# input 
["in", "France:", "22", "Rue", "du", "Débarcadère", ",", "75017", "Paris", ",", "France", "where", "they", "are"] 
MyModule.process(tokens) 

# output 
["in", "France:", %Address{ 
    street: "Rue du Débarcadère", 
    street_number: 22, 
    zip: 75017, 
    city: "Paris", 
    country: "France" 
}, "where", "they", "are"] 

# input 
["in", "the", "USA:", "125", "Maiden", "Lane", ",", "11th", "Floor", 
"New", "York", ",", "NY", "10038", "USA", "where", "they", "are"] 

# output 
["in", "the", "USA:", %Address{ 
    street: "Maiden Lane", 
    street_number: 125, 
    floor: 11, 
    zip: 10038, 
    city: "New York", 
    state: "NY", 
    country: "USA" 
}, "where", "they", "are"] 

Address構造体の中に一連のトークンを回すには、いくつかの国が必要になります特定のロジック(住所の書式設定のさまざまな方法など)がありますが、これは利用可能です。さらに、トークン(「:」で終わるトークンなど)を調べることで、適切な構文解析ロジック(つまり、住所が入っている国)に切り替えることができるとします。

もう一度、私は何を達成しようとしている:

  1. トークンを超える反復1は、特殊なケース(続く国の名前を「:」)トリガするまで
  2. すると、関連するすべてのトークン(プロセストークンを消費最初の例では、「フランス」を「22」)から
  3. は、構造体(%Address{}
  4. は、最初の未処理トークンに反復継続(「」)
でそれらを置き換えます

reduceのいくつかの形式が適切と思われるが、私はそれをしたい場所reduce自体は反復継続しないだろう、とreduce_whileはいずれかのチケットではないようです...

そして、それは行うべきではありません違いが、私は、例えば、より高いレベルで同じロジック/プロセスを適用することができ、より高いレベルのデータ構造を構成したいと思います:あなたはこのためStream.unfold/2を使用することができます

# input 
["the", "Mirabeau", "restaurant", "at", %Address{...}, "where", "he", "cooked"] 

# output 
["the", %Place{ 
    name: "Mirabeau", 
    type: :restaurant, 
    location: %Address{...} 
}, "where", "he", "cooked"] 

答えて

2

。すべてのトークンを初期アキュムレータとして渡し、関数からタームと新しいアキュムレータのタプルを返します。国名の後に:が続く場合は、さらに多くのトークンを消費して残りのトークンを返すことができます。他の人にとっては、頭を戻して尾を続けるだけです。ここで

は、これを行う小さな例です:

["in", "France:", "22", "Rue", "du", "Débarcadère", ",", "75017", 
"Paris", ",", "France", "where", "they", "are", "in", "the", "USA:", "125", 
"Maiden", "Lane", ",", "11th", "Floor", "New", "York", ",", "NY", "10038", 
"USA", "where", "they", "are"] 
|> Stream.unfold(fn 
    [] -> nil 
    [h | t] -> 
    if String.ends_with?(h, ":") do 
     {street, t} = Enum.split_while(t, &(&1 != ",")) 
     ["," | t] = t 
     {rest, t} = Enum.split_while(t, &(&1 <> ":" != h)) 
     [country | t] = t 
     {%{street: street, rest: rest, country: country}, t} 
    else 
     {h, t} 
    end 
end) 
|> Enum.to_list 
|> IO.inspect 

出力:

["in", 
%{country: "France", rest: ["75017", "Paris", ","], 
    street: ["22", "Rue", "du", "Débarcadère"]}, "where", "they", "are", "in", 
"the", 
%{country: "USA", rest: ["11th", "Floor", "New", "York", ",", "NY", "10038"], 
    street: ["125", "Maiden", "Lane"]}, "where", "they", "are"] 
関連する問題