2009-11-19 14 views
14

In F # voglio trasformare una lista di caratteri in una stringa. Si consideri il seguente codice:Come modificare l'elenco dei caratteri in stringa?

let lChars = ['a';'b';'c'] 

Se faccio semplicemente lChars.ToString, ottengo "[ 'a'; 'b'; 'c']". Sto cercando di ottenere "abc". Mi rendo conto che potrei probabilmente fare un List.reduce per ottenere l'effetto che sto cercando, ma sembra che ci dovrebbe essere qualche primitivo costruito nella libreria per farlo.

Per dare un piccolo contesto a questo, sto facendo qualche manipolazione sui singoli caratteri in una stringa e quando ho finito, voglio visualizzare la stringa risultante.

Ho provato a googling questo e nessuna gioia in questo modo. Devo solo mordere il proiettile e creare un'espressione List.reduce per eseguire questa trasformazione o esiste un modo più elegante per farlo?

risposta

23

Hai provato

System.String.Concat(Array.ofList(lChars)) 
+10

nuove System.String (lchars |> Array.of_list) Opere altrettanto bene anche – Juliet

+0

@JaredPar, grazie! Proprio quello che ha ordinato il dottore. Ho pensato che ci doveva essere un modo semplice per ottenere la stringa che volevo. @Juliet, dovresti averlo postato come risposta :-) Avrei votato perché è anche un ottimo suggerimento. –

+3

Se usi .NET 4 o successivo, anche 'System.String.Concat (lChars)' fa il trucco. –

2
['a';'b';'c'] |> List.fold_left (fun acc c -> acc^(string c)) "" 

Modificato: Qui è un altro modo divertente per fare il vostro compito:

type t = 
    | N 
    | S of string 
    static member Zero 
    with get() = N 
    static member (+) (a: t, b: t) = 
    match a,b with 
     | S a, S b -> S (a+b) 
     | N, _ -> b 
     | _, N -> a 

let string_of_t = function 
    |N -> "" 
    |S s -> s 

let t_of_char c = S (string c) 

['a'; 'b'; 'c'] |> List.map t_of_char |> List.sum |> string_of_t 

Purtroppo, solo estendendo System.String con gli 'Zero' non permette di usare List.sum con le stringhe.

Modificato (risposta a Juilet): Sì, hai ragione, la piega a sinistra è lenta. Ma so più lento destra piegare :):

#r "FSharp.PowerPack" 

List.fold_right (String.make 1 >> (^)) ['a';'b';'c'] "" 

e, naturalmente, non v'è semplice e veloce:

new System.String(List.to_array ['1';'2';'3']) 
+0

Una cosa @ssp, ho provato concatenando una stringa con l'operatore^e il compilatore mi ha dato un avvertimento circa la compatibilità OCaml. Cioè, mi ha avvertito che dovrei usare + per concatenare le stringhe. –

+3

fold_left è divertente, ma è necessario ricordare che aggiungendo le stringhe è O (n), e aggiungendo le stringhe un carattere alla volta è O (n^2)! – Juliet

6

In quanti modi si può costruire una stringa in F #? Ecco un altro pugno:

let chars = ['H';'e';'l';'l';'o';',';' ';'w';'o';'r';'l';'d';'!'] 

//Using an array builder 
let hw1 = new string [|for c in chars -> c|] 

//StringBuilder-Lisp-like approach 
open System.Text 
let hw2 = 
    string (List.fold (fun (sb:StringBuilder) (c:char) -> sb.Append(c)) 
         (new StringBuilder()) 
         chars) 

//Continuation passing style 
let hw3 = 
    let rec aux L k = 
     match L with 
     | [] -> k "" 
     | h::t -> aux t (fun rest -> k (string h + rest)) 
    aux chars id 

Edit: timing può essere interessante? Ho girato hw1..3 in funzioni e nutriti loro una lista di 500000 caratteri casuali:

  • HW1: 51MS
  • HW2: 16ms
  • HW3: ehm ... abbastanza a lungo per crescere la barba? Penso che abbia mangiato tutta la mia memoria.
1

e ho usato 'sprintf' mi sembra più facile:

let t = "Not what you might expect" 
let r = [ for i in "aeiou" -> i] 
let q = [for a in t do if not (List.exists (fun x -> x=a) r) then yield a] 
let rec m = function [] -> "" | h::t -> (sprintf "%c" h) + (m t) 
printfn "%A" (m q) 
+0

indentare il codice di 4 spazi per una migliore formattazione –

+1

A cosa servono le parentesi graffe? –

0

La seguente soluzione funziona per me:

let charList = ["H";"E";"L";"L";"O"] 

let rec buildString list = 
    match list with 
    | [] -> "" 
    | head::tail -> head + (buildString tail) 

let resultBuildString = buildString charList 
+0

Nota: questo è un elenco di stringhe, non di caratteri. Inoltre, hai appena reimplementato List.fold –

Problemi correlati