I have an incoming string 68016101061B4A60193390662046804020422044204000420040402060226024676DB16
and I want to convert into 0x68 0x01 0x61 0x01 0x06 0x1B 0x4
If you want to use pure LINQ, you can do something along the lines of
data
.Select((x,i) => (Index: i, Value: x))
.GroupBy(tuple => tuple.Index / 2, tuple => tuple.Value, (_,values) => "0x" + string.Join("",values))
.Select(x => Convert.ToByte(x, 16))
.ToArray();
if you want a ridiculous one-liner.
In Linq:
string src = "040204220442040004200404020602260246";
string res = Enumerable.Range(0, src.Length)
.Where(i => i % 2 == 0)
.Aggregate<int, string, string>("", (s, i) => s + " 0x" + src.Substring(i, 2), (s) => s.Trim());
or - if the input string is very long - to better the performance:
string res = Enumerable.Range(0, src.Length)
.Where(i => i % 2 == 0)
.Aggregate<int, StringBuilder, string>(new StringBuilder(), (sb, i) => sb.Append(" 0x").Append(src.Substring(i, 2)), (sb) => sb.ToString().Trim());
in both cases the res
contains "0x04 0x02 0x04 0x22 0x04 0x42 0x04 0x00 0x04 0x20 0x04 0x04 0x02 0x06 0x02 0x26 0x02 0x46"
If you want the result as an array of bytes AND to handle input strings with an uneven number of digits as well it could be done as follwing:
string src = "040204220442040004200404020602260246";
if (src.Length % 2 == 1) src += "0";
byte[] res = Enumerable.Range(0, src.Length)
.Where(i => i % 2 == 0)
.Select(i => Byte.Parse(src.Substring(i, 2), System.Globalization.NumberStyles.AllowHexSpecifier))
.ToArray();
You can use a regular expression to do this:
var regex = new Regex(@"(\d{2})");
string aString = "040204220442040004200404020602260246";
string replaced = regex.Replace(aString, "x$1 ");
Fiddle
EDIT It seems like you need bytes instead of a string, you can use one of the Linq based answers suggested here or a simple loop:
if ((aString.Length % 2) != 0)
{
// Handle invalid input
}
var bytes = new byte[aString.Length / 2];
int index = 0;
for (int i = 0; i < aString.Length; i += 2)
{
string digits = aString.Substring(i, 2);
byte aByte = (byte)int.Parse(digits, NumberStyles.HexNumber);
bytes[index++] = aByte;
}
port.Write(bytes, 0, bytes.Length);
Note that if GC pressure became an issue, you could use ReadOnlySpan<char>
.
Fiddle