How To Change List of Chars To String?

20,941

Solution 1

Have you tried

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

Solution 2

How many ways can you build a string in F#? Here's another handful:

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: timings may be interesting? I turned hw1..3 into functions and fed them a list of 500000 random characters:

  • hw1: 51ms
  • hw2: 16ms
  • hw3: er... long enough to grow a beard? I think it just ate all of my memory.

Solution 3

Didn't see this one here, so:

let stringFromCharList (cl : char list) =
    String.concat "" <| List.map string cl

"" is just an empty string.

FSI output:

> stringFromCharList ['a'..'d'];;
val it : string = "abcd"

EDIT:

Didn't like this syntax coming back to this so here's a more canonically functional one:

['a'..'z'] |> List.map string |> List.reduce (+)

Solution 4

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

Edited: Here is yet another funny way to do your task:

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

Sadly, just extending System.String with 'Zero' member does not allow to use List.sum with strings.

Edited (answer to Juilet): Yes, you are right, left fold is slow. But i know more slow right fold :) :

#r "FSharp.PowerPack"

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

and of course there is fast and simple:

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

Solution 5

And i used 'sprintf' seems to me easier:

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)
Share:
20,941

Related videos on Youtube

Onorio Catenacci
Author by

Onorio Catenacci

I've been writing software for 25+ years now. I pursue ornithology as an avocation. If you want to contact me, contact me via my blog. http://onor.io av00M52Kg330gF5G

Updated on July 09, 2022

Comments

  • Onorio Catenacci
    Onorio Catenacci almost 2 years

    In F# I want to transform a list of chars into a string. Consider the following code:

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

    If I simply do lChars.ToString, I get "['a';'b';'c']". I'm trying to get "abc". I realize I could probably do a List.reduce to get the effect I'm looking for but it seems like there should be some primitive built into the library to do this.

    To give a little context to this, I'm doing some manipulation on individual characters in a string and when I'm done, I want to display the resulting string.

    I've tried googling this and no joy that way. Do I need to just bite the bullet and build a List.reduce expression to do this transformation or is there some more elegant way to do this?

  • Juliet
    Juliet over 14 years
    new System.String(lchars |> Array.of_list) works just as well too.
  • Onorio Catenacci
    Onorio Catenacci over 14 years
    @JaredPar, thanks! Just what the doctor ordered. I figured there must be some simple way to get at the string I wanted. @Juliet, you should have posted that as an answer :-) I would have voted it up because it's also an excellent suggestion.
  • Onorio Catenacci
    Onorio Catenacci over 14 years
    One thing @ssp, I did try concatenating a string with the ^ operator and the compiler gave me a warning about OCaml compatibility. That is, it warned me that I should use + to concatenate strings.
  • Juliet
    Juliet over 14 years
    fold_left is fun, but you need to remember that appending strings is O(n), and appending strings one char at a time is O(n^2)!
  • Onorio Catenacci
    Onorio Catenacci almost 11 years
    What are the curly braces for?
  • Sean U
    Sean U about 10 years
    If you're using .NET 4 or later, System.String.Concat(lChars) also does the trick.
  • ghord
    ghord over 8 years
    let result = lChars |> Array.ofList |> String works too in F# 4.0
  • arash maleki
    arash maleki about 8 years
    Note - this is a list of strings, not chars. Also, you have just reimplemented List.fold
  • phoog
    phoog over 5 years
    let r = List.ofSeq "aeiou" seems simpler to me.
  • enedil
    enedil over 4 years
    The last version is nice and everything, but it is quadratic in the size of list.
  • tykom
    tykom over 4 years
    /shrug don't use it on big lists, I guess. How would you reduce the time complexity?
  • Petetheodddog
    Petetheodddog almost 4 years
    This wasn't the right answer but it came in useful, thank you