web-dev-qa-db-ja.com

テキストでパターンマッチングを行うにはどうすればよいですか?

テキストに対してパターンマッチングを実行するとします。具体的には、最初の文字のパターンマッチングを行います。

たとえば、「about」と「analog」に一致するが「beta」には一致しないパターンを作成するにはどうすればよいですか?

私はこれを試しました:

defmodule MatchStick do
    def doMatch([head | tail]) when head == "a" do 1 end
    def doMatch([head | tail]) do 0 end
end

res = MatchStick.doMatch("abcd");

文字リストも試しました:

defmodule MatchStick do
    def doMatch([head | tail]) when head == 'a' do 1 end
    def doMatch([head | tail]) do 0 end
end

res = MatchStick.doMatch('abcd');

どちらもうまくいきませんでした。テキストを一致させる適切な方法は何ですか?

24
epotter
defmodule MatchStick do
  def doMatch("a" <> rest) do 1 end
  def doMatch(_) do 0 end
end

見られる文字列連結演算子を使用する必要があります here

例:

iex> "he" <> rest = "hello"
"hello"
iex> rest
"llo"
34
Kyle

Elixirでは、単一引用符付き文字列は二重引用符付き文字列とはかなり異なります。一重引用符で囲まれた文字列は、基本的に整数のリストであり、各整数は文字を表します。したがって、これらは文字リストとも呼ばれます。これらは、Erlangとの互換性のために主に使用されます。これは、Erlang文字列が機能するためです。リストを使用するのと同じように、単一引用符で囲んだ文字列を使用できます。

iex> hd('a')
97

iex> [97 | rest] = 'abcd'
'abcd'
iex> rest
'bcd'

iex> 'ab' ++ rest = 'abcd'
'abcd'
iex> rest
'cd'

一重引用符で囲まれた文字列の照合関数は次のようになります。

def match('a' ++ rest), do: 1
def match(_), do: 0

Elixirは、すべての整数が有効な文字を表す場合、リストを非表示にし、文字列として表示します。 Elixirをだまして文字リストの内部表現を表示するには、無効な文字である0を挿入できます。

iex> string = 'abcd'
'abcd'
iex> string ++ [0]
[97, 98, 99, 100, 0]

ただし、通常はElixirで二重引用符で囲まれた文字列を使用します。これらはUTF-8を正しく処理し、操作がはるかに簡単で、すべての内部Elixirモジュール(たとえば、有用なStringモジュール)で使用されます。二重引用符で囲まれた文字列はバイナリなので、他のバイナリタイプとして扱うことができます。

iex> <<97, 98, 99, 100>>
"abcd"
iex> <<1256 :: utf8>>
"Ө"

iex> <<97>> <> rest = "abcd"
"abcd"
iex> rest
"bcd"

iex> "ab" <> rest = "abcd"
"abcd"
iex> rest
"cd"

二重引用符で囲まれた文字列の一致関数は次のようになります。

def match("a" <> rest), do: 1
def match(_), do: 0

エリクサーは、バイナリ文字列の内部表現も非表示にします。それを明らかにするために、もう一度0を挿入できます。

iex> string = "abcd"
"abcd"
iex> string <> <<0>>
<<97, 98, 99, 100, 0>>

最後に、単一引用符付き文字列と二重引用符付き文字列の間で変換するには、関数to_stringおよびto_charlistを使用できます。

iex> to_string('abcd')
"abcd"
iex> to_charlist("abcd")
'abcd'

それらを検出するには、is_listおよびis_binaryを使用できます。これらはガード句でも機能します。

iex> is_list('abcd')
true
iex> is_binary('abcd')
false
iex> is_list("abcd")
false
iex> is_binary("abcd")
true

たとえば、二重引用符で囲まれたバージョンを単一引用符で囲まれた文字列と互換性を持たせるには、次のようにします。

def match(str) when is_list(str), do: match(to_string(str))
def match("a" <> rest), do: 1
def match(_), do: 0
18
Patrick Oscity

誰かが必要な場合に備えて。既知の中間にある文字列の一部を照合する必要があり、その長さがわかっている場合は、バイナリ照合を使用できます。

iex(1)> <<"https://", locale::binary-size(2), ".wikipedia.com" >> = "https://en.wikipedia.com" 
"https://en.wikipedia.com"
iex(2)> locale
"en"
3

文字リストの先頭でパターンマッチングを行う場合、2番目のコードスニペットで行う必要があるわずかな違いが1つあります。

'a'は実際には1つの要素を持つ文字リストであるため、文字リストの先頭との比較は常にfalseになります。 charlistは実際には整数値のリストです:

iex> 'abcd' == [97, 98, 99, 100]
true

Char aは整数97と同じです。 Elixirで文字の整数コードを取得するには、その前に?を付けます。

iex> ?a == 97
true
iex> ?a == hd('a')
true

したがって、guard句では、head == ?aまたはより単純に一致させる必要があります。

defmodule MatchStick do
    def doMatch([?a | _tail]), do: 1
    def doMatch(_), do: 0
end
1
Erik J