سؤال

انا املك List<bool> التي أريد تحويلها إلى byte[]. وبعد كيف أقوم بهذا العمل؟list.toArray() يخلق أ bool[].

هل كانت مفيدة؟

المحلول

فيما يلي مناهضين، اعتمادا على ما إذا كنت ترغب في حزم البتات في البايتات، أو لديك العديد من البايتات حسب البتات الأصلية:

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

نصائح أخرى

يمكنك استخدام LinQ. هذا لن يكون فعالا، ولكن سيكون بسيطا. أنا أفترض أنك تريد بايت واحد لكل بوول.

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

إجابة مارك جيدة بالفعل، ولكن ...

افترض أنت نوع الشخص المريح للقيام بتنسيق بعض الشيء، أو فقط أريد أن أكتب رمز أقل و ضغط بعض الأداء الإضافي، ثم هذا الرمز هنا هو لك يا سيدي جيد / مدام:

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

يفعل الشيء نفسه بالضبط كود مارك، إنه موجز أكثر فقط.

بالطبع إذا كنا حقا تريد أن تذهب كل شيء يمكننا أن ننفث ذلك أيضا ...
... وبينما نحن في ذلك يتيح رمي الكرة منحنى على نوع المرتجع!

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

نصيحة: كما ترون أنا تضمنت الرمز لإرجاع byte[] كتعليقات. ما عليك سوى التعليق على بيانات العائدين بدلا من ذلك إذا كان هذا هو ما تريد / تحتاجه.


تلميحات twiddling:
التحول 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>

إذا كان لديك أي تحكم في نوع القائمة، فحاول تحقيقها قائمة، والتي ستنتج بعد ذلك البايت [] على Toarray (). إذا كان لديك قائمة صفيف، يمكنك استخدام:

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

للحصول على القائمة، يمكنك إنشاء واحدة مع قائمتك غير المحددة للماءات كمدخل للمشكل، ثم إنتاج ToArray ()؟ أو نسخ كل عنصر، صب بايت جديد من bool؟

بعض المعلومات حول نوع القائمة التي قد تساعد.

إلقاء نظرة على bitconverter. صف دراسي. اعتمادا على الطبيعة الدقيقة لمتطلباتك، قد يحل مشكلتك بدقة بدقة.

نهج Linq آخر، أقل فعالية من @ HFCS101 ولكنه سيعمل بسهولة من أجل أنواع القيمة الأخرى أيضا:

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

أو ال IEnumerable نهج إجابة Anorzaken:

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

وطبق تفريغ أين paddingEnd يعني مقدار البتات للتخلص من البايت الأخير إلى تفريغ:

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;
            }
        }
    }
}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top