문제

나는있다 List<bool> 내가 a로 변환하고 싶다 byte[]. 어떻게해야합니까?list.toArray() a 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 당 하나의 바이트를 원한다고 가정합니다.

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

마크의 대답은 이미 좋지만 ...

가정합니다 당신은 비트 widdling을하는 편안한 사람입니다. 그리고 더 많은 성능을 짜내십시오. 그러면이 코드는 당신을위한 것입니다.

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

팁: 보시다시피, 나는 반환을위한 코드를 포함시켰다. byte[] 의견으로. 원하는/필요한 경우 두 가지 수율 진술을 대신 주석하십시오.


트위 딩 힌트 :
이동 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 ()에서 바이트를 생성합니다. ArrayList가있는 경우 다음을 사용할 수 있습니다.

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

목록을 얻으려면 지정되지 않은 목록 반복자로 생성자에 대한 입력으로 하나를 만들 수 있었고 ToArray ()를 생성 할 수 있습니까? 아니면 각 항목을 복사하여 BOOL에서 새 바이트에 캐스팅 하시겠습니까?

어떤 유형의 목록에 대한 정보가 도움이 될 수 있습니다.

살펴보십시오 비트 컨버터 수업. 요구 사항의 정확한 특성에 따라 문제를 매우 깔끔하게 해결할 수 있습니다.

@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