2014-09-17 12 views
14

Diciamo che voglio modellare la corrispondenza con il testo. Nello specifico, voglio abbinare la corrispondenza alla prima lettera.Come si può eseguire la corrispondenza del modello sul testo?

Ad esempio, come posso creare un modello che corrisponda a "circa" e "analogico" ma non a "beta"?

Ho provato questo:

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

Ho anche provato liste di caratteri:

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

Né funzionato. Qual è il modo corretto per abbinare il testo?

risposta

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

È necessario utilizzare l'operatore di concatenazione di stringhe visto here

Esempio:

iex> "he" <> rest = "hello" 
"hello" 
iex> rest 
"llo" 
12

In Elixir, singole stringhe tra virgolette sono molto diverse dalle corde doppie virgolette. Le singole stringhe tra virgolette sono essenzialmente elenchi di numeri interi, in cui ogni intero rappresenta un carattere. Pertanto, vengono anche chiamati elenchi di caratteri. Sono usati principalmente per compatibilità con Erlang, perché è così che funzionano le corde di Erlang. È possibile utilizzare singole stringhe tra virgolette, proprio come si usa liste:

iex> hd('a') 
97 

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

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

La funzione di corrispondenza per singole stringhe tra virgolette sarebbe simile a questa:

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

Elixir nasconderà la lista da voi e visualizzarlo come una stringa, quando tutti gli interi rappresentano caratteri validi. Per ingannare Elixir in che vi mostra la rappresentazione interna di una lista di caratteri, è possibile inserire un 0, che è un carattere non valido:

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

Tuttavia, si potrebbe usare le stringhe in genere doppio citato in Elisir, perché questi manico UTF- 8 correttamente, sono molto più facili da utilizzare e vengono utilizzati da tutti i moduli Elixir interni (ad esempio l'utile modulo String). Doppi stringhe tra virgolette sono i binari, in modo da poterli trattare come qualsiasi altro tipo binario:

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 funzione partita per corde doppie citati sarebbe simile a questa:

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

Elixir nasconde la rappresentazione interna di stringhe binarie pure. A rivelarlo, si può ancora inserire un 0: Infine

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

, per la conversione tra stringhe singole citato e doppie stringhe tra virgolette è possibile utilizzare le funzioni to_string e to_char_list:

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

rilevarli, è possibile utilizzare is_list e is_binary. Questi funzionano anche nelle clausole di guardia.

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

Ad esempio, per rendere la versione a doppia citato compatibile con singole stringhe tra virgolette:

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

Ho una domanda su questa riga di codice: "iex> [97 | rest] = 'abcd'" Capisco perché funziona, ma non è molto leggibile. C'è un modo per fare qualcosa di simile a questo "iex> ['a' | rest] = 'abcd'"? – epotter

+0

Ecco perché ho aggiunto un esempio con l'operatore di concatenazione lista '++'. In alternativa, converti in una stringa binaria :-) –

+1

@epotter: '[? A | resto] = 'abcd'' – Kabie

0

Se si desidera pattern match sulla testa di un charlist, c'è una leggera differenza è necessario fare nel tuo secondo snippet di codice.

'a' è in realtà un elenco di caratteri con un elemento, quindi il confronto con la testa di un elenco di caratteri sarà sempre falso. Un charlist è in realtà un elenco di valori interi:

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

Il char a equivale a intero 97. È possibile ottenere il codice intero di un personaggio di Elixir facendolo precedere da un ?, quindi:

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

Quindi nel tuo clausola di guardia, si vorrà abbinare head == ?a, o più semplicemente:

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