F # byte [] & # 8594; hex & # 8594; string conversion

I have an array of bytes as input. I would like to convert this array to a string containing a hexadecimal representation of the values ​​of the array. This is the F # code:

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

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

This gives the result that I need, but I would like to make it more compact so that I have only one function. I could not find a function that would execute a string representation of each byte at the end of ByteToHex.
I tried Array.concat, concat_map, I tried with lists, but the best I could get was an array or list of strings.

Questions:

  • What would be the easiest, most elegant way to do this?
  • Is there a formatting string in F # so that I can replace String.Format from the system assembly?

Input Example: [| 0x24uy; 0xA1uy; 0x00uy; 0x1Cuy |] should create the string "24A1001C"

+5
source share
5 answers

There is nothing wrong with your example. If you want to get it up to one expression, use the String.contcat method.

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

Under the hood, String.concat will simply call String.Join. Your code may be subject to change, although based on your sample you import System. This can create a name resolution conflict between F # String and System.String.

+5
source

If you want to convert and copy in one step fold- your answer. sprintfis an F # string formatting function.

let ByteToHex = Array.fold (fun state x-> state + sprintf "%02X" x) ""
+2
source

:

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.

+1

Looks good. To point to another, in my opinion, a very useful function in the Printf module, take a look ksprintf. It passes the result of the formatted string to a function of your choice (in this case, an identification function).

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

Honestly, this does not look terrible (although I also have very little F # experience). Does F # provide an easy way to iterate (foreach)? If it was C #, I could use something like (where rawis the argument byte[]):

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

I wonder how this translates as F # ...

-1
source

All Articles