2010-08-03 12 views
6

Właśnie uczę się F # i konwertuję bibliotekę metod rozszerzania C# na F #. Obecnie pracuję na realizację funkcji o nazwie ConvertFirstLetterToUppercase oparta na # realizacji C poniżej:Optymalizacja manipulacji ciągiem 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); 
} 

F # realizacja

[<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()) 

Może ktoś mi pokazać bardziej zwięzłego realizacji wykorzystujący bardziej naturalny F # składnia?

+0

Dziękuję wszystkim za odpowiedzi, nauczyłem się kilku nowych operatorów i korzystania z dopasowywania wzorców. :-) Myślę, że następny krok? Test wydajności? lol –

Odpowiedz

5

coś takiego?

[<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

Podoba mi się ten, tylko notatkę, można połączyć zerowe lub puste kontrole tablicowe z następującymi, aby zmniejszyć liczbę linii: | null | [||] -> to –

4

Spróbuj po

[<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) 

Funkcja tryFind zwróci pierwszy element do którego powraca true lambda. Ponieważ zawsze zwraca wartość true, po prostu zwróci pierwszy element lub None. Po ustanowieniu istnieje co najmniej jeden element wiesz data nie null i stąd mogą dzwonić podciągu

+0

Podoba mi się rozwiązanie! Miałem trochę nadziei, że konsole będą działały z tablicami, więc mogłem dopasować wzorce do wyrażenia, które faktycznie stworzyło wynik, ale niestety, to nie jest częścią implementacji. : -/ –

17
open System 

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

Zastosowanie:

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

Teraz jeśli chcesz czegoś bardziej wydajnego niż podciągi, spróbuj 'let chars = s.ToCharArray(); znaki. [0] <- Char.ToUpper (chars. [0]); new String (chars) ' – Juliet

+0

+1, uwielbiam używać [n..n]. Nie widziałem, żeby było stosowane w dobrym przypadku bofer. – JaredPar

+0

Czy wersja macierzy jest naprawdę szybsza? Wersja substring tworzy kopię prawie całego ciągu znaków (s. [1 ..]), a następnie tworzy kolejny łańcuch, gdy ten ciąg zostanie dodany do pierwszego znaku. Wersja tablicy kopiuje ciąg do tablicy, a następnie tablica jest kopiowana do ciągu znaków. Wydaje się, że dwie operacje kopiowania są w obu kierunkach - czy konwersja macierzy jest szybsza niż kopiowanie ciągów znaków? –

2

Nie ma nic złego w korzystaniu z funkcji biblioteki .NET z języka .NET. Może bezpośrednie tłumaczenie twojej metody rozszerzenia C# jest najbardziej odpowiednie, szczególnie w przypadku tak prostej funkcji. Chociaż kusiłbym się, by użyć takiej składni jak Juliet, tylko dlatego, że jest fajna.

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

Naprawdę wolę korzystać z funkcji języka wewnętrznego w stosunku do API Framework, tylko ze względu na mniej szczegółowy styl języka. –

+0

Wydaje mi się, że to dla mnie czyste rozwiązanie, nawet jeśli nie wydaje się ono bardzo idiomatyczne. – Daniel

Powiązane problemy