2009-11-19 11 views
14

En F #, je veux transformer une liste de caractères en une chaîne. Considérez le code suivant:Comment faire pour modifier la liste des caractères en chaîne?

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

Si je fais simplement lChars.ToString, je reçois "[ 'a', 'b', 'c']". J'essaie d'obtenir "abc". Je me rends compte que je pourrais probablement faire un List.reduce pour obtenir l'effet que je cherche, mais il semble qu'il devrait y avoir une primitive construite dans la bibliothèque pour le faire.

Pour donner un peu de contexte à ceci, je fais une manipulation sur les caractères individuels dans une chaîne et quand j'ai fini, je veux afficher la chaîne résultante. J'ai essayé de googler ceci et pas de joie de cette façon. Dois-je juste mordre la balle et construire une expression List.reduce pour faire cette transformation ou y at-il une façon plus élégante de le faire?

Répondre

23

Avez-vous essayé

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

nouvelles System.String (lchars |> Array.of_list) travaux tout aussi bien aussi. – Juliet

+0

@JaredPar, merci! Juste ce que le docteur à prescrit. Je me suis dit qu'il devait y avoir un moyen simple d'obtenir la corde que je voulais. @Juliet, vous devriez avoir posté cela comme réponse :-) J'aurais voté parce que c'est aussi une excellente suggestion. –

+3

Si vous utilisez .NET 4 ou plus tard, 'System.String.Concat (lChars)' fait aussi l'affaire. –

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

Modifié: Voici encore une autre façon amusante de faire votre tâche:

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 

Malheureusement, juste étendre System.String avec un membre 'Zéro' ne permet pas d'utiliser List.sum avec des chaînes. Édité (réponse à Juilet): Oui, vous avez raison, le pli gauche est lent. Mais je sais plus lent pli droit :):

#r "FSharp.PowerPack" 

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

et bien sûr, il est simple et rapide:

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

Une chose @ssp, j'ai essayé de concaténer une chaîne avec l'opérateur^et le compilateur m'a donné un avertissement sur la compatibilité OCaml. Autrement dit, il m'a averti que je devrais utiliser + pour concaténer les chaînes. –

+3

fold_left est amusant, mais vous devez vous rappeler que l'ajout de chaînes est O (n), et l'ajout de chaînes un caractère à la fois est O (n^2)! – Juliet

6

Combien de façons pouvez-vous construire une chaîne en F #? Voici une autre poignée:

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: horaires peuvent être intéressants? Je me suis tourné hw1..3 en fonctions et les nourrissais une liste de 500000 caractères aléatoires:

  • hw1: 51MS
  • hw2: 16ms
  • HW3: euh ... assez longtemps pour pousser la barbe? Je pense qu'il a juste mangé toute ma mémoire.
1

et moi 'sprintf' me semble plus 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

indenter votre code par 4 espaces pour un meilleur formatage –

+1

À quoi servent les accolades? –

0

La solution suivante fonctionne pour moi:

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

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

let resultBuildString = buildString charList 
+0

Note - ceci est une liste de chaînes, pas de caractères. En outre, vous venez de réimplémenter List.fold –

Questions connexes