Alex 75
Alex 75

Reputation: 3236

F# - Hex to ASCII

  1. There is something better than Convert for the 2 operations in the following code?
  2. I'd like to know if this solution (sprintf) is better (or worst) than one with the use of Substring
  3. I'd like to know if using a list here would be better
  4. The previous 2 questions change within the size of the string? (a short one (less than 20 chars) or a long one)

Assume the input is always correct (no odd lenght).

let hexToAscii (hex:string) =         
    let chars = Array.zeroCreate<char> (hex.Length/2)
    for i in 1..2..hex.Length-1 do
        chars.[i/2] <- Convert.ToChar(Convert.ToByte(sprintf "%c%c" hex.[i-1] hex.[i] , 16))

    String(chars)

Is a question like this better suited for https://codereview.stackexchange.com ?

Upvotes: 3

Views: 198

Answers (1)

Koenig Lear
Koenig Lear

Reputation: 2436

A more idiomatic solution would be this:

First deal with a single byte e.g. "42"

let hexByteToAscii (s:string) =
    System.Convert.ToByte(s,16)
    |> System.Convert.ToChar

and let's have helper function to convert char[] to string

let charsToString (chars:char[]) =
    new string (chars)

Then let's deal with a longer sequence like "4142" by taking chunks of 2 characters and use our existing function to deal with bytes.

let hexToAscii (value:string) =
    value
    |>Seq.chunkBySize 2
    |>Seq.map ( hexByteToAscii << charsToString)
    |>Seq.toArray
    |>charsToString 

You can test it:

hexToAscii "4142" // "AB"

In terms of performance both are asymptotically O(n) where n is the size of your input string. I wouldn't worry much more unless your n> 10000. Which doesn't seem to be your scenario. Perhaps there's some gains to be made by implementing your own hex byte to ascii function using a dictionary table.

Upvotes: 4

Related Questions