LoginSignup
1
0

英文を分割する

Last updated at Posted at 2023-09-03

文字列のパース

F.o.R(Frame of Reference)のような構造図を実現するために、まずは文字列を単語単位で分割したい。

例えば"This is a pen."という文字列を["This", "is", "a", "pen", "."]というリストに変えたい。
String.split()だと空白で分割されるため、"pen."になってしまい、ピリオドだけ分割できない。

test "split" do
    assert "This is a pen." |> String.split() == ["This", "is", "a", "pen", "."]
  end

実行結果

code:  assert "This is a pen." |> String.split() == ["This", "is", "a", "pen", "."]
     left:  ["This", "is", "a", "pen."]
     right: ["This", "is", "a", "pen", "."]

ピリオドを考慮する

そこで文字列の最後にピリオドが含まれているかを調べる関数を作り、ピリオドが含まれていれば、分割するようにしたい。

文字列の最後にピリオドが含まれているかどうか

def contains_terminator?(token) do
    last_char_code =
      token
      |> String.to_charlist()
      |> List.last()

      last_char = <<last_char_code::utf8>>
      if last_char == "." do
        true
      else
        false
      end
  end
test "contains_terminator" do
    assert "This" |> contains_terminator? == false
    assert "is" |> contains_terminator? == false
    assert "a" |> contains_terminator? == false
    assert "pen." |> contains_terminator? == true
  end

想定通りに動くことを確認できた。

ピリオドが含まれていたら分割する

def split_terminator([]), do: []

  def split_terminator([head | tail]) do
   
    if contains_terminator?(head) do
      [token_a, token_b] = head |> String.split(".")
      [token_a, ".", token_b | split_terminator(tail)]
    else
      [head | split_terminator(tail)]
    end
  end
test "'This is a pen.'" do
    assert ["This", "is", "a", "pen."] |> split_terminator() == ["This", "is", "a", "pen", "."]
  end

テストコードを実行したが、エラーになってしまった。

Assertion with == failed
     code:  assert ["This", "is", "a", "pen."] |> split_terminator() == ["This", "is", "a", "pen", "."]
     left:  ["This", "is", "a", "pen", ".", ""]
     right: ["This", "is", "a", "pen", "."]

どうやら最後に空白の要素ができてしまうらしい。
アドホックなやり方だが、 Enum.filter(fn x -> x !== "" and x !== nil end) を加えて空白の要素を除去するようにした。

def split_terminator([head | tail]) do
    # {result, terminator} = contains_terminator?(head)

    if contains_terminator?(head) do
      [token_a, token_b] = head |> String.split(".")
      [token_a, ".", token_b | split_terminator(tail)]
      |> Enum.filter(fn x -> x !== "" and x !== nil end)
    else
      [head | split_terminator(tail)]
    end
  end
1
0
1

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0