Как изменить список символов в строку?

В F # я хочу преобразовать список символов в строку. Рассмотрим следующий код:

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

Если я просто делаю lChars.ToString, я получаю "['a'; 'b'; 'c']". Я пытаюсь получить "abc". Я понимаю, что, возможно, я мог бы сделать List.reduce, чтобы получить эффект, который я ищу, но похоже, что в библиотеку должен быть встроенный примитив, чтобы сделать это.

Чтобы дать небольшой контекст этому, я делаю некоторые манипуляции с отдельными символами в строке, и когда я закончил, я хочу отобразить результирующую строку.

Я пробовал эту игру и без радости. Нужно ли просто укусить пулю и создать выражение List.reduce для этого преобразования или есть ли еще более элегантный способ сделать это?

Ответы

Ответ 1

Вы пробовали

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

Ответ 2

Сколько способов вы можете построить строку в F #? Здесь еще несколько:

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

Изменить: могут быть интересны тайминги? Я превратил hw1..3 в функции и подал им список из 500000 случайных символов:

  • hw1: 51ms
  • hw2: 16ms
  • hw3: er... достаточно долго, чтобы вырастить бороду? Я думаю, что он просто съел всю мою память.

Ответ 3

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

Отредактировано: Вот еще один забавный способ выполнить вашу задачу:

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

К сожалению, просто расширение System.String с помощью элемента "Zero" не позволяет использовать List.sum со строками.

Отредактировано (ответ на Juilet): Да, вы правы, левая складка медленная. Но я знаю более медленную правую складку:):

#r "FSharp.PowerPack"

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

и, конечно, быстро и просто:

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

Ответ 4

Не видел этого здесь, так что:

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

"" это просто пустая строка.

Выход FSI:

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

РЕДАКТИРОВАТЬ:

Не понравился этот синтаксис, возвращающийся к этому, поэтому здесь более канонически функциональный:

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

Ответ 5

И я использовал 'sprintf', мне кажется легче:

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)

Ответ 6

Для меня работает следующее решение:

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

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

let resultBuildString = buildString charList