Frage

Ich habe eine List<bool>, die ich zu einem byte[] konvertieren möchten. Wie mache ich das? list.toArray() schafft eine bool[].

War es hilfreich?

Lösung

Hier zwei Ansätze, je nachdem, ob die Bits in Bytes packen wollen, oder wie viele Bytes als ursprünglichen Bits haben:

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

Andere Tipps

Sie können LINQ verwenden. Dies wird nicht effizient sein, sondern wird einfach sein. Ich gehe davon aus, dass Sie ein Byte pro Bool wollen.

bool[] a = new bool[] { true, false, true, true, false, true };
byte[] b = (from x in a select x ? (byte)0x1 : (byte)0x0).ToArray();

Marc Antwort ist schon gut, aber ...

Unter der Annahme, Sie sind die Art von Person, die bequem ist Bit-Fummel tun, oder wollen einfach nur weniger Code schreiben und etwas mehr Leistung Squeeze-out, dann diesen hier Code ist gut für Sie Herr / gnädige Frau:

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

Es tut genau dasselbe wie Marcs Code, es ist nur prägnanter.

Natürlich, wenn wir wirklich alle wollen gehen wir es entrollen konnte ...
... und während wir an ihn wirft in einer Kurve Ball auf dem Rückgabetyp!

läßt
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;
}

Tipp: Wie man sehen kann ich den Code für die Rückgabe eines byte[] als Kommentare enthalten. kommentieren Sie einfach die beide Ertragsrechnung statt, wenn das ist, was Sie wollen / müssen.


twiddling Hinweise:
x >> 3 Shifting ist ein billiger x / 8.
Masking x & 0x07 ist ein billiger x % 8.
Masking x & ~0x07 ist ein billiger x - x % 8.


Edit: Hier ist ein Beispiel Dokumentation:

    /// <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>

Wenn Sie die Kontrolle über die Art der Liste haben, versuchen Sie es eine Liste zu machen, die dann das Byte produzieren wird [] auf ToArray (). Wenn Sie eine Arraylist haben, können Sie:

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

Um die Liste zu erhalten, können Sie eine mit Ihrer unspecified Liste Iterator als eine Eingabe an den Konstruktor schaffen könnten, und erzeugt dann den ToArray ()? Oder jedes Element kopieren, auf ein neues Byte von Bool Gießen?

Einige Informationen auf, welche Art von Liste ist es könnte helfen.

Haben Sie einen Blick auf die BitConverter Klasse. Abhängig von der genauen Art Ihrer Anforderung, kann es Ihr Problem ganz ordentlich lösen.

Ein weiterer LINQ Ansatz, weniger wirksam als @ hfcs101 sind aber für andere Werttypen leicht funktionieren würde auch:

var a = new [] { true, false, true, true, false, true };
byte[] b = a.Select(BitConverter.GetBytes).SelectMany(x => x).ToArray();

oder die IEnumerable Annäherung an AnorZaken Antwort :

static IEnumerable<byte> PackBools(IEnumerable<bool> bools)
{
    int bitIndex = 0;
    byte currentByte = 0;
    foreach (bool val in bools) {
        if (val)
            currentByte |= (byte)(1 << bitIndex);
        if (++bitIndex == 8) {
            yield return currentByte;
            bitIndex = 0;
            currentByte = 0;
        }
    }
    if (bitIndex != 8) {
        yield return currentByte;
    }
}

Und das nach dem Auspacken, wo paddingEnd die Menge an Bits bedeutet, aus dem letzten Byte zu verwerfen auszupacken:

static IEnumerable<bool> UnpackBools(IEnumerable<byte> bytes, int paddingEnd = 0)
{
    using (var enumerator = bytes.GetEnumerator()) {
        bool last = !enumerator.MoveNext();
        while (!last) {
            byte current = enumerator.Current;
            last = !enumerator.MoveNext();
            for (int i = 0; i < 8 - (last ? paddingEnd : 0); i++) {
                yield return (current & (1 << i)) != 0;
            }
        }
    }
}
Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top