Linq 将 bool[] 转换为 byte[]

Linq to convert bool[] to byte[]

我有一个数组中的布尔值列表

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
               };

是否有使用 linq 将其转换为 byte[] 的简单方法?

//expected result
byte[] result = { 255, 1, 3 };

"Is there a easy way with linq to convert this into byte[]?"我不知道我是否会说它简单,它肯定不漂亮,但这似乎有效:

        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();

所以您有一个布尔值序列,您希望将每 8 个连续布尔值的值转换为一个字节,其中位模式等于 8 个布尔值,最高有效位 (MSB) 在前。

See how to convert an sequence of 8 Booleans into one byte

转换分两步完成:

  • 将您的序列分成 8 个布尔值组
  • 将每组 8 个布尔值转换为一个字节

为了保持可读性,我创建了 IEnumerable 的扩展函数。参见 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;
    }
}

用法如下:

IEnumerable<bool> items = ...
IEnumerable<Byte> convertedItems = items.ToBytes();