2010-08-03 54 views
6

我剛剛學習F#並將C#擴展方法的庫轉換爲F#。我目前正在實施一個名爲ConvertFirstLetterToUppercase功能基於以下的C#實現: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#實現

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

有人能告訴我利用更自然的F#更簡潔的方式句法?

+0

謝謝大家的回答,我學到了一些新的操作符以及如何使用模式匹配。 :-)我猜下一步?性能測試?大聲笑 – 2010-08-03 19:50:47

回答

5

像這樣的事情?

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

我喜歡這個,只是一個說明,你可以結合空或空陣列檢查與以下,以減少行數: | null | [||] - >這個 – 2010-08-03 19:44:07

4

請嘗試以下

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

tryFind函數將返回該拉姆達返回true的第一要素。由於它總是返回true,它將簡單地返回第一個元素或None。一旦你確定有至少一個元素是你知道datanull,因此可以調用子串

+0

我喜歡解決方案!我很希望缺點會與數組一起工作,所以我可以在實際創建結果的表達式上進行模式匹配,但是,這不是實現的一部分。 : -/ – 2010-08-03 17:41:14

17
open System 

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

用法:

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

現在,如果你想要比子字符串更有效一些,請嘗試'let chars = s.ToCharArray();字符。[0] < - Char.ToUpper(chars。[0]);新的字符串(字符)' – Juliet 2010-08-03 17:43:21

+0

+1,喜歡使用[n..n]。還沒有看到,在一個好例子bofer應用。 – JaredPar 2010-08-03 17:43:34

+0

陣列版本真的更快嗎?子字符串版本幾乎形成了整個字符串的一個副本(s。[1 ..]),然後在將該字符串添加到第一個字符時創建另一個字符串。數組版本將字符串複製到數組,然後將數組複製到字符串。似乎有兩種複製操作 - 或者數組轉換比字符串複製更快? – 2010-08-03 21:07:27

2

從.NET語言使用.NET庫函數沒有任何問題。也許直接翻譯你的C#擴展方法是最合適的,特別是對於這樣一個簡單的函數。儘管我很想用朱麗葉那樣的切片語法,只是因爲它很酷。

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

我真的更喜歡使用框架API的內在語言功能,這是因爲語言風格不那麼冗長。 – 2010-08-03 19:42:42

+0

這對我來說似乎是一個乾淨的解決方案,即使它看起來不太習慣。 – Daniel 2011-01-31 15:33:28