Toshi
Toshi

Reputation: 2608

Linq to convert bool[] to byte[]

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

Answers (2)

Harald Coppoolse
Harald Coppoolse

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:

  • Divide your sequence into groups of 8 Booleans
  • Convert every group of 8 Booleans into one Byte

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

kanders84152
kanders84152

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

Related Questions