2010-08-03 8 views
6

Acabo de aprender F # y he estado convirtiendo una biblioteca de métodos de extensión C# en F #. Actualmente estoy trabajando en la implementación de una función llamada ConvertFirstLetterToUppercase basado en la C# aplicación a continuación:Optimización de la manipulación de la secuencia F #

public static string ConvertFirstLetterToUppercase(this string value) { 
    if (string.IsNullOrEmpty(value)) return value; 
    if (value.Length == 1) return value.ToUpper(); 
    return value.Substring(0, 1).ToUpper() + value.Substring(1); 
} 

El F # aplicación

[<System.Runtime.CompilerServices.ExtensionAttribute>] 
module public StringHelper 
    open System 
    open System.Collections.Generic 
    open System.Linq 

    let ConvertHelper (x : char[]) = 
     match x with 
      | [| |] | null -> "" 
      | [| head; |] -> Char.ToUpper(head).ToString() 
      | [| head; _ |] -> Char.ToUpper(head).ToString() + string(x.Skip(1).ToArray()) 

    [<System.Runtime.CompilerServices.ExtensionAttribute>] 
    let ConvertFirstLetterToUppercase (_this : string) = 
     match _this with 
     | "" | null -> _this 
     | _ -> ConvertHelper (_this.ToCharArray()) 

Alguien me puede mostrar una aplicación más concisa utilizando más natural F # ¿sintaxis?

+0

Gracias a todos por las respuestas, aprendí algunos operadores nuevos y cómo usar la coincidencia de patrones. :-) Supongo que el próximo paso? ¿Pruebas de rendimiento? lol –

Respuesta

5

Algo como esto?

[<System.Runtime.CompilerServices.ExtensionAttribute>] 
module public StringHelper = 
[<System.Runtime.CompilerServices.ExtensionAttribute>] 
let ConvertFirstLetterToUppercase (t : string) = 
    match t.ToCharArray() with 
    | null -> t 
    | [||] -> t 
    | x -> x.[0] <- Char.ToUpper(x.[0]); System.String(x) 
+2

Me gusta esta, solo una nota, puede combinar las comprobaciones de matrices vacías o nulas con lo siguiente para reducir el recuento de líneas: | null | [||] -> esto –

4

intente lo siguiente

[<System.Runtime.CompilerServices.ExtensionAttribute>] 
module StringExtensions = 
    let ConvertFirstLetterToUpperCase (data:string) = 
     match Seq.tryFind (fun _ -> true) data with 
     | None -> data 
     | Some(c) -> System.Char.ToUpper(c).ToString() + data.Substring(1) 

La función tryFind devolverá el primer elemento para el que el lambda vuelve true. Como siempre devuelve verdadero, simplemente devolverá el primer elemento o None. Una vez que haya establecido que hay al menos un elemento sabes data ¿no null y por lo tanto puede llamar Subcadena

+0

¡Me gusta la solución! Esperaba que los contras funcionaran con las matrices, así que podía hacer una coincidencia de patrones en la expresión que realmente creaba el resultado, pero, por desgracia, eso no forma parte de la implementación. : -/ –

17
open System 

type System.String with 
    member this.ConvertFirstLetterToUpperCase() = 
     match this with 
     | null -> null 
     | "" -> "" 
     | s -> s.[0..0].ToUpper() + s.[1..] 

Uso:

> "juliet".ConvertFirstLetterToUpperCase();; 
val it : string = "Juliet" 
+1

Ahora, si quiere algo un poco más eficiente que las subcadenas, intente 'let chars = s.ToCharArray(); caracteres. [0] <- Char.ToUpper (caracteres [0]); nueva cadena (caracteres) ' – Juliet

+0

+1, adora el uso de [n..n]. No he visto eso aplicado en un buen caso Bofer. – JaredPar

+0

¿La versión de matriz es realmente más rápida? La versión de subcadena hace una copia de casi toda la cadena (s. [1 ..]) y luego se crea otra cadena cuando esa cadena se agrega al primer carácter. La versión de matriz copia la cadena a una matriz, luego la matriz se copia a una cadena. Parece que hay 2 operaciones de copia en ambos sentidos, ¿o la conversión de matriz es más rápida que la copia de cadenas? –

2

No hay nada de malo con el uso de las funciones de biblioteca .NET desde un idioma .NET. Quizás una traducción directa de su método de extensión C# sea la más apropiada, particularmente para una función tan simple. Aunque estaría tentado de utilizar la sintaxis de corte como lo hace Juliet, simplemente porque es genial.

open System 
open System.Runtime.CompilerServices 

[<Extension>] 
module public StringHelper = 

    [<Extension>] 
    let ConvertFirstLetterToUpperCase(this:string) = 
     if String.IsNullOrEmpty this then this 
     elif this.Length = 1 then this.ToUpper() 
     else this.[0..0].ToUpper() + this.[1..] 
+0

Realmente prefiero el uso de las características del lenguaje intrínseco sobre las API de Framework solo por el estilo de lenguaje menos detallado. –

+0

Esto parece una solución limpia para mí, incluso si no parece muy idiomático. – Daniel

Cuestiones relacionadas