2008-12-21 108 views
5

我有字節數組作爲輸入。我想將該數組轉換爲包含數組值的十六進制表示的字符串。這是F#代碼:f#字節[] - >十六進制 - >字符串轉換

let ByteToHex bytes = 
    bytes 
    |> Array.map (fun (x : byte) -> String.Format("{0:X2}", x)) 

let ConcatArray stringArray = String.Join(null, (ByteToHex stringArray)) 

這產生了我需要的結果,但我想使它更緊湊,因此我只有一個函數。 我無法找到連接ByteToHex的末尾 上每個字節的字符串表示形式的函數。
我試過Array.concat,concat_map,我試過列表,但是我能得到的最好的數組或字符串列表。

問題:

  1. 什麼是最簡單,最優雅的方式來做到這一點?
  2. 在F#中有字符串格式化結構,以便我可以從系統程序集中替換String.Format?

輸入示例:[| 0x24uy; 0xA1uy; 0x00uy; 0x1Cuy |]應該會產生字符串「24A1001C」

回答

5

沒有什麼內在的錯誤你的榜樣。如果你想把它歸結爲一個表達式,然後使用String.contcat方法。

let ByteToHex bytes = 
    bytes 
    |> Array.map (fun (x : byte) -> System.String.Format("{0:X2}", x)) 
    |> String.concat System.String.Empty 

在引擎蓋下,String.concat只會調用String.Join。您的代碼可能不得不輕微更改,因爲根據您導入系統的樣本。這可能會在F#String和System.String之間創建名稱解析衝突。

+0

完美。我嘗試過使用String.Concat,但我沒有添加「System.String.Empty」參數。 – zendar 2008-12-21 15:02:40

-1

說實話,這看起來並不可怕(雖然我也有非常小F#的經驗)。 F#提供了一種簡單的迭代方法(foreach)嗎?如果這是C#,我可能會使用類似(其中rawbyte[]參數):

 StringBuilder sb = new StringBuilder(); 
     foreach (byte b in raw) { 
      sb.Append(b.ToString("x2")); 
     } 
     return sb.ToString() 

我不知道怎麼說轉化爲F#...

+0

呵呵,我可以WITE它在F#這種方式,但檢查該演示盧卡·波隆尼http://channel9.msdn.com/pdc2008/TL11/ 在最初幾分鐘內有大約勢在必行之間差異的解釋聲明式編程和示例是關於迭代器的。 – zendar 2008-12-21 13:18:54

+0

夠公平的。那麼,我會觀察更好的答案。我可以學習一些F#; - p – 2008-12-21 13:28:32

0

看起來很好。在我看來,只要指出另一個,在Printf模塊中非常有用的功能,請看ksprintf。它將格式化字符串的結果傳遞給您所選擇的函數(在這種情況下爲身份函數)。

val ksprintf : (string -> 'd) -> StringFormat<'a,'d> -> 'a 
    sprintf, but call the given 'final' function to generate the result. 
1

下面是另一個答案:

let hashFormat (h : byte[]) = 
    let sb = StringBuilder(h.Length * 2) 
    let rec hashFormat' = function 
    | _ as currIndex when currIndex = h.Length -> sb.ToString() 
    | _ as currIndex -> 
     sb.AppendFormat("{0:X2}", h.[currIndex]) |> ignore 
     hashFormat' (currIndex + 1) 
    hashFormat' 0 

這一個好處是,它的尾遞歸,它的預分配,這將需要轉換的字符串生成器空間的確切數額字節數組轉換爲十六進制字符串。

爲背景,我有這個模塊中:

module EncodingUtils 

open System 
open System.Text 
open System.Security.Cryptography 
open Newtonsoft.Json 

let private hmacmd5 = new HMACMD5() 
let private encoding = System.Text.Encoding.UTF8 
let private enc (str : string) = encoding.GetBytes str 
let private json o = JsonConvert.SerializeObject o 
let md5 a = a |> (json >> enc >> hmacmd5.ComputeHash >> hashFormat) 

含義我可以通過MD5任何物體,並取回它的JSON哈希值。

2

如果你想變換和積累在一個步驟,fold是你的答案。 sprintf是F#字符串格式函數。

let ByteToHex = Array.fold (fun state x-> state + sprintf "%02X" x) "" 
相關問題