Reputation: 2608
I have a list of boolean values within a array
bool[] items = { true, true, true, true, true, true, true, true, //#1
false, false, false, false, false, false, false, true, //#2
false, false, false, false, false, false, true , true //#3
};
Is there a easy way with linq to convert this into byte[]
?
//expected result
byte[] result = { 255, 1, 3 };
Upvotes: 0
Views: 683
Reputation: 30454
So you have a sequence of Booleans and you want to convert the values of every 8 consecutive Booleans into one Byte where the bit pattern equals the 8 Booleans with most significant bit (MSB) first.
See how to convert an sequence of 8 Booleans into one byte
Converting is done in two steps:
To keep it readable I create extension functions of IEnumerable. See Extension methods demystified
static class EnumerableExtensions
{
public static IEnumerable<Byte> ToBytes(this IEnumerable<Bool> bools)
{
// converts the bools sequence into Bytes with the same 8 bit
// pattern as 8 booleans in the array; MSB first
if (bools == null) throw new ArgumentNullException(nameof(bools));
// while there are elements, take 8, and convert to Byte
while (bools.Any())
{
IEnumerable<bool> eightBools = bools.Take(8);
Byte convertedByte = eightBools.ToByte();
yield return convertedByte();
// remove the eight bools; do next iteration
bools = bools.Skip(8);
}
}
public static Byte ToByte(this IEnumerable<bool> bools)
{ // converts the first 8 elements of the bools sequence
// into one Byte with the same binary bit pattern
// example: 00000011 = 3
if (bools == null) throw new ArgumentNullException(nameof(bools));
var boolsToConvert = bools.Take(8);
// convert
byte result = 0;
int index = 8 - source.Length;
foreach (bool b in boolsToConvert)
{
if (b)
result |= (byte)(1 << (7 - index));
index++;
}
return result;
}
}
Usage will be as follows:
IEnumerable<bool> items = ...
IEnumerable<Byte> convertedItems = items.ToBytes();
Upvotes: 1
Reputation: 1341
"Is there a easy way with linq to convert this into byte[]
?" I don't know if I'd call it easy, and it's certainly not pretty, but this seems to work:
byte[] result = Enumerable.Range(0, items.Length / 8)
.Select(i => (byte)items.Select(b => b ? 1 : 0)
.Skip(i * 8)
.Take(8)
.Aggregate((k, j) => 2 * k + j))
.ToArray();
Upvotes: 2