modo più semplice di pattern matching contro l'avviamento della lista in F #
-
05-09-2019 - |
Domanda
Sto cercando di scrivere una funzione di elaborazione di stringa in F #, che assomiglia a questo:
let rec Process html =
match html with
| '-' :: '-' :: '>' :: tail -> ("→" |> List.of_seq) @ Process tail
| head :: tail -> head :: Process tail
| [] -> []
Il mio modello di corrispondenza di espressione contro diversi elementi è un brutto (il tutto '-' :: '-' :: '>'
) bit. C'è un modo per renderlo migliore? Inoltre, è quello che sto facendo efficiente se dovessi elaborare grandi testi? O c'è un altro modo?
Chiarimento : quello che voglio dire è, per esempio, essere in grado di scrivere qualcosa del genere:
match html with
| "-->" :: tail ->
Soluzione
Sono d'accordo con gli altri che l'utilizzo di un elenco di caratteri per fare seria manipolazione di stringhe non è probabilmente l'ideale. Tuttavia, se si desidera continuare a utilizzare questo approccio, un modo per ottenere qualcosa di simile a quello che stai chiedendo è quello di definire un modello attivo. Per esempio:
let rec (|Prefix|_|) s l =
if s = "" then
Some(Prefix l)
else
match l with
| c::(Prefix (s.Substring(1)) xs) when c = s.[0] -> Some(Prefix xs)
| _ -> None
Quindi è possibile utilizzare le cose come:
let rec Process html =
match html with
| Prefix "-->" tail -> ("→" |> List.of_seq) @ Process tail
| head :: tail -> head :: Process tail
| [] -> []
Altri suggerimenti
C'è un modo per renderlo migliore?
Certo:
let process (s: string) = s.Replace("-->", "→")
Inoltre, è quello che sto facendo efficiente se dovessi elaborare grandi testi?
No, è incredibilmente inefficiente. Assegnazione e garbage collection è costoso e si sta facendo così per ogni singolo carattere.
O c'è un altro modo?
Prova il membro Replace
. Se questo non funziona, provare un'espressione regolare. Se questo non funziona, scrivere un lexer (per esempio usando fslex
). In definitiva, ciò che si vuole per l'efficienza è una macchina a stati l'elaborazione di un flusso di caratteri e di emettere il suo risultato mutando sul posto.
Penso che si dovrebbe evitare di utilizzare l'elenco
Per problemi semplici, utilizzando String e StringBuilder direttamente come detto Brian è probabilmente il modo migliore. Per problemi più complessi, si consiglia di controllare alcuni sofisticata libreria di analisi come FParsec per F #.
Questa domanda può essere qualche aiutare a darvi idee per un altro modo di affrontare il problema -. utilizzando l'elenco <> per contenere le linee, ma utilizzando le funzioni di stringa all'interno di ogni riga