two strings separate multiple how characters string f# char seq

strings - split string python multiple delimiter



F#, char seq-> cuerdas (4)

F # ha ganado la capacidad de usar constructores como funciones desde que se hizo esta pregunta hace 5 años. Yo usaría String(Char[]) para convertir caracteres en una cadena. Puedes convertir String.ToCharArray desde una secuencia de F # o una lista de F #, pero probablemente solo use el módulo de matriz F # usando el método String.ToCharArray también.

printfn "%s" ("abcdef01234567".ToCharArray() |> Array.take 5 |> String)

Si realmente quisieras usar una secuencia de caracteres, entonces puedes canalizarla a una cadena como esta:

printfn "%s" ("abcdef01234567" |> Seq.take 5 |> Array.ofSeq |> String)

Una pregunta rápida que puede ser más de una perorata (pero espero ser iluminado en su lugar).

En F #, una cadena es compatible con Seq, por lo que "abcd" |> Seq.map f funcionará en una cadena.

Esta es una facilidad brillante para trabajar con cadenas, por ejemplo, para tomar los primeros 5 caracteres de una cadena:

"abcdef01234567" |> Seq.take 5

O eliminar caracteres duplicados:

"abcdeeeeeee" |> Seq.distinct

El problema es que una vez que tienes el resultado de la secuencia de caracteres, se vuelve extremadamente incómodo convertir esto nuevamente en una cadena, String.concat "" requiere que los miembros sean cadenas, así que termino haciendo esto mucho:

"abcdef01234567" |> Seq.take 5 |> Seq.map string |> String.concat ""

Tanto que tengo una función que uso en el 90% de mis proyectos:

let toString : char seq -> string = Seq.map string >> String.concat ""

Siento que esto es exagerado, pero en todas partes busco una alternativa que me encuentre con cosas atroces como StringBuilder o alinear un lambda y usar lo nuevo:

"abcdef01234567" |> Seq.take 5 |> Seq.toArray |> fun cs -> new string (cs) (* note you cannot just |> string *)

Mi (tal vez loca) expectativa de que me gustaría ver en el idioma es que cuando se usa Seq en una cadena, la firma de tipo de la expresión resultante debería ser cadena -> cadena. Es decir, lo que entra es lo que sale. "abcd" |> Seq.take 3 = "abc".

¿Hay alguna razón por la que mis expectativas de manipulación de cuerdas de alto nivel se confundan en este caso?

¿Alguien tiene una recomendación para abordar esto de una manera agradable? Siento que debo estar perdiendo algo.


F # tiene un módulo de cadena que contiene parte de la funcionalidad del módulo Seq especializada para cadenas.


Las funciones en el módulo Seq solo tratan con secuencias, es decir, cuando se les llama con una string , solo "ven" una Seq<char> y operan en consecuencia. Incluso si hicieron una comprobación especial para ver si el argumento era una string y realizaron alguna acción especial (por ejemplo, una versión optimizada de la función solo para cadenas), aún tendrían que devolverla como un Seq<char> para apaciguar el sistema de tipo F #, en cuyo caso, tendría que verificar el valor de retorno en todas partes para ver si en realidad era una string .

La buena noticia es que F # tiene accesos directos incorporados para algunos de los códigos que está escribiendo. Por ejemplo:

"abcdef01234567" |> Seq.take 5

se puede acortar a:

"abcdef01234567".[..4] // Returns the first _5_ characters (indices 0-4).

Sin embargo, algunos de los otros aún tendrán que usar Seq o escribir su propia implementación optimizada para operar en cadenas.

Aquí hay una función para obtener los distintos caracteres en una cadena:

open System.Collections.Generic let distinctChars str = let chars = HashSet () let len = String.length str for i = 0 to len - 1 do chars.Add str.[i] |> ignore chars


Solo estaba investigando esto yo mismo. Encontré que System.String.Concat funciona bastante bien, por ejemplo

"abcdef01234567" |> Seq.take 5 |> String.Concat;;

asumiendo que has abierto el System .