9

List<bool>変換したいものがありbyte[]ます。どうすればこれを行うことができますか? list.toArray()を作成しbool[]ます。

4

7 に答える 7

26

ビットをバイトにパックするか、元のビットと同じ数のバイトにするかによって、2 つの方法があります。

    bool[] bools = { true, false, true, false, false, true, false, true,
                     true };

    // basic - same count
    byte[] arr1 = Array.ConvertAll(bools, b => b ? (byte)1 : (byte)0);

    // pack (in this case, using the first bool as the lsb - if you want
    // the first bool as the msb, reverse things ;-p)
    int bytes = bools.Length / 8;
    if ((bools.Length % 8) != 0) bytes++;
    byte[] arr2 = new byte[bytes];
    int bitIndex = 0, byteIndex = 0;
    for (int i = 0; i < bools.Length; i++)
    {
        if (bools[i])
        {
            arr2[byteIndex] |= (byte)(((byte)1) << bitIndex);
        }
        bitIndex++;
        if (bitIndex == 8)
        {
            bitIndex = 0;
            byteIndex++;
        }
    }
于 2009-04-03T08:53:46.080 に答える
4

マークの答えはすでに良いですが...

あなたが少しいじるのに慣れている人、または単にコードを減らしてパフォーマンスを絞り出したいだけの人だと仮定すると、このコードはあなたのためのものです。

byte[] PackBoolsInByteArray(bool[] bools)
{
    int len = bools.Length;
    int bytes = len >> 3;
    if ((len & 0x07) != 0) ++bytes;
    byte[] arr2 = new byte[bytes];
    for (int i = 0; i < bools.Length; i++)
    {
        if (bools[i])
            arr2[i >> 3] |= (byte)(1 << (i & 0x07));
    }
}

これは Marc のコードとまったく同じことを行いますが、より簡潔になっています。

もちろん、本当にやりたい場合は、アンロールすることもできます...
...そして、リターン型に変化球を投入しましょう!

IEnumerable<byte> PackBoolsInByteEnumerable(bool[] bools)
{
    int len = bools.Length;
    int rem = len & 0x07; // hint: rem = len % 8.

    /*
    byte[] byteArr = rem == 0 // length is a multiple of 8? (no remainder?)
        ? new byte[len >> 3] // -yes-
        : new byte[(len >> 3)+ 1]; // -no-
     */

    const byte BZ = 0,
        B0 = 1 << 0, B1 = 1 << 1, B2 = 1 << 2, B3 = 1 << 3,
        B4 = 1 << 4, B5 = 1 << 5, B6 = 1 << 6, B7 = 1 << 7;

    byte b;
    int i = 0;
    for (int mul = len & ~0x07; i < mul; i += 8) // hint: len = mul + rem.
    {
        b = bools[i] ? B0 : BZ;
        if (bools[i + 1]) b |= B1;
        if (bools[i + 2]) b |= B2;
        if (bools[i + 3]) b |= B3;
        if (bools[i + 4]) b |= B4;
        if (bools[i + 5]) b |= B5;
        if (bools[i + 6]) b |= B6;
        if (bools[i + 7]) b |= B7;

        //byteArr[i >> 3] = b;
        yield return b;
    }

    if (rem != 0) // take care of the remainder...
    {
        b = bools[i] ? B0 : BZ; // (there is at least one more bool.)

        switch (rem) // rem is [1:7] (fall-through switch!)
        {
            case 7:
                if (bools[i + 6]) b |= B6;
                goto case 6;
            case 6:
                if (bools[i + 5]) b |= B5;
                goto case 5;
            case 5:
                if (bools[i + 4]) b |= B4;
                goto case 4;
            case 4:
                if (bools[i + 3]) b |= B3;
                goto case 3;
            case 3:
                if (bools[i + 2]) b |= B2;
                goto case 2;
            case 2:
                if (bools[i + 1]) b |= B1;
                break;
            // case 1 is the statement above the switch!
        }

        //byteArr[i >> 3] = b; // write the last byte to the array.
        yield return b; // yield the last byte.
    }

    //return byteArr;
}

ヒント:ご覧のとおり、abyte[]をコメントとして返すコードを含めました。それが必要な場合は、代わりに 2 つの yield ステートメントをコメントアウトするだけです。


いじりのヒント:
シフトx >> 3の方が安上がりx / 8です。
マスキングx & 0x07の方が安いx % 8です。
マスキングx & ~0x07の方が安いx - x % 8です。


編集: ここにいくつかのドキュメントの例があります:

    /// <summary>
    /// Bit-packs an array of booleans into bytes, one bit per boolean.
    /// </summary><remarks>
    /// Booleans are bit-packed into bytes, in order, from least significant
    /// bit to most significant bit of each byte.<br/>
    /// If the length of the input array isn't a multiple of eight, then one
    /// or more of the most significant bits in the last byte returned will
    /// be unused. Unused bits are zero / unset.
    /// </remarks>
    /// <param name="bools">An array of booleans to pack into bytes.</param>
    /// <returns>
    /// An IEnumerable&lt;byte&gt; of bytes each containing (up to) eight
    /// bit-packed booleans.
    /// </returns>
于 2016-04-12T12:05:37.993 に答える
3

LINQ を使用できます。これは効率的ではありませんが、単純になります。ブールごとに1バイトが必要だと仮定しています。

bool[] a = new bool[] { true, false, true, true, false, true };
byte[] b = (from x in a select x ? (byte)0x1 : (byte)0x0).ToArray();
于 2009-04-03T08:58:41.450 に答える
0

リストのタイプを制御できる場合は、リストにしてみてください。これにより、ToArray() で byte[] が生成されます。ArrayList がある場合は、次を使用できます。

(byte[])list.ToArray(typeof(byte));

List を取得するには、未指定のリスト反復子をコンストラクターへの入力として作成し、ToArray()? または、bool から新しいバイトにキャストして、各項目をコピーしますか?

リストの種類に関する情報が役立つ場合があります。

于 2009-04-03T08:56:38.397 に答える
0

BitConverterクラスを見てください。要件の正確な性質によっては、問題を非常にうまく解決できる場合があります。

于 2009-04-03T08:58:01.437 に答える
0

別の LINQ アプローチは、@ hfcs101 のものより効果的ではありませんが、他の値の型でも簡単に機能します。

var a = new [] { true, false, true, true, false, true };
byte[] b = a.Select(BitConverter.GetBytes).SelectMany(x => x).ToArray();
于 2016-01-04T17:55:45.673 に答える