Ответ 1
defmodule MatchStick do
def doMatch("a" <> rest) do 1 end
def doMatch(_) do 0 end
end
Вам нужно использовать оператор конкатенации строк, который отображается здесь
Пример:
iex> "he" <> rest = "hello"
"hello"
iex> rest
"llo"
Предположим, что я хочу сопоставить шаблон с текстом. В частности, я хочу совпадение шаблонов в первой букве.
Например, как создать шаблон, который будет соответствовать "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');
Ни один из них не работал. Каков правильный способ соответствия текста?
defmodule MatchStick do
def doMatch("a" <> rest) do 1 end
def doMatch(_) do 0 end
end
Вам нужно использовать оператор конкатенации строк, который отображается здесь
Пример:
iex> "he" <> rest = "hello"
"hello"
iex> rest
"llo"
В 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
Elixir также скрывает внутреннее представление двоичных строк. Чтобы показать это, вы можете снова вставить 0
:
iex> string = "abcd"
"abcd"
iex> string <> <<0>>
<<97, 98, 99, 100, 0>>
Наконец, для преобразования между строками с одинарными и двойными to_string
вы можете использовать функции 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
Если вы хотите совместить шаблон с заголовком charlist, вам нужно сделать небольшое различие во втором фрагменте кода.
'a'
на самом деле является charlist с одним элементом, поэтому сравнение с головой charlist всегда будет ложным. Charlist действительно представляет собой список целых значений:
iex> 'abcd' == [97, 98, 99, 100]
true
char a
означает целое число 97
. Вы можете получить целочисленный код символа в Elixir, указав его ?
, поэтому:
iex> ?a == 97
true
iex> ?a == hd('a')
true
Итак, в вашем предложении охраны вам нужно сопоставить head == ?a
или проще:
defmodule MatchStick do
def doMatch([?a | _tail]), do: 1
def doMatch(_), do: 0
end
На всякий случай кому-то нужно. Если вам нужно сопоставить часть строки, которая находится в известной середине, и вы знаете ее длину, вы можете использовать двоичное сопоставление:
iex(1)> <<"https://", locale::binary-size(2), ".wikipedia.com" >> = "https://en.wikipedia.com"
"https://en.wikipedia.com"
iex(2)> locale
"en"