web-dev-qa-db-fra.com

Comment le filtrage de texte peut-il être effectué?

Disons que je veux faire correspondre un motif à un texte. Plus précisément, je veux faire correspondre le motif sur la première lettre.

Par exemple, comment créer un modèle qui correspond aux mots "à propos de" et "analogique" mais pas à "bêta"?

J'ai essayé ceci:

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");

J'ai aussi essayé des listes de personnages:

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');

Ni travaillé. Quelle est la bonne façon de faire correspondre le texte?

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

Vous devez utiliser l'opérateur de concaténation de chaînes vu ici

Exemple:

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

Dans Elixir, les chaînes simples citées sont assez différentes des chaînes doubles. Les chaînes simples entre guillemets sont essentiellement des listes d'entiers, chaque entier représentant un caractère. Par conséquent, ils s'appellent également des listes de caractères. Ils sont principalement utilisés pour la compatibilité avec Erlang, car c'est ainsi que fonctionnent les chaînes Erlang. Vous pouvez utiliser des chaînes entre guillemets comme vous utiliseriez des listes:

iex> hd('a')
97

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

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

La fonction de correspondance pour les chaînes entre guillemets ressemblerait à ceci:

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

Elixir vous cachera la liste et l'affichera sous forme de chaîne, lorsque tous les entiers représentent des caractères valides. Pour inciter Elixir à vous montrer la représentation interne d'une liste de caractères, vous pouvez insérer un 0, qui est un caractère invalide:

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

Cependant, les chaînes entre guillemets doubles dans Elixir sont généralement utilisées, car elles gèrent correctement UTF-8, sont beaucoup plus faciles à utiliser et sont utilisées par tous les modules Elixir internes (par exemple, le module utile String). Les chaînes à double guillemet sont des fichiers binaires, vous pouvez donc les traiter comme n'importe quel autre type binaire:

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"

La fonction de correspondance pour les chaînes à double guillemet ressemblerait à ceci:

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

Elixir masquera également la représentation interne des chaînes binaires. Pour le révéler, vous pouvez à nouveau insérer un 0:

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

Enfin, pour convertir des chaînes entre guillemets simples et des chaînes à guillemets doubles, utilisez les fonctions to_string et to_char_list:

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

Pour les détecter, vous pouvez utiliser is_list et is_binary. Celles-ci fonctionnent également dans les clauses de garde.

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

Par exemple, pour rendre la version à double guillemet compatible avec des chaînes à guillemets simples:

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

Si vous souhaitez appliquer une correspondance de modèle en tête d'une liste de caractères, vous devez faire une petite différence dans votre deuxième extrait de code.

'a' est en fait une charlist avec un élément, donc comparer avec la tête d'une charlist sera toujours faux. Une charlist est vraiment une liste de valeurs entières:

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

Le caractère a équivaut à un entier 97. Vous pouvez obtenir le code entier d'un caractère dans Elixir en le faisant précéder d'un ?, ainsi:

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

Donc, dans votre clause de garde, vous voudrez faire correspondre head == ?a, ou plus simplement:

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