Trying to solve this with LINQ was fun!
Warning: For entertainment purposes only - do not use the below performance abominations in real code!
First try - group pairs of uints, create three bytes out of each pair, flatten list:
byte[] packedNumbers = (from i in Enumerable.Range(0, unpackedNumbers.Length)
group unpackedNumbers[i] by i - (i % 2) into pairs
let n1 = pairs.First()
let n2 = pairs.Skip(1).First()
let b1 = (byte)(n1 >> 4)
let b2 = (byte)(((n1 & 0xF) << 4) | (n2 & 0xF00) >> 8)
let b3 = (byte)(n2 & 0xFFFF)
select new[] { b1, b2, b3 })
.SelectMany(b => b).ToArray();
Or slightly more compact, but less readable:
byte[] packedNumbers = unpackedNumbers
.Select((Value, Index) => new { Value, Index })
.GroupBy(number => number.Index - (number.Index % 2))
.SelectMany(pair => new byte[] {
(byte)(pair.First().Value >> 4),
(byte)(((pair.First().Value & 0xF) << 4) | (pair.Skip(1).First().Value & 0xF00) >> 8),
(byte)(pair.Skip(1).First().Value & 0xFFFF) }).ToArray();
Strings anyone?
char[] hexChars = unpackedNumbers.SelectMany(n => n.ToString("X4").Substring(1, 3)).ToArray();
byte[] packedNumbers = (from i in Enumerable.Range(0, hexChars.Length / 2)
select byte.Parse(hexChars[i * 2].ToString() + hexChars[i * 2 + 1], NumberStyles.HexNumber))
.ToArray();