Search code examples
c#linq

Use LINQ to XOR Bytes Together


How can I use LINQ to to XOR bytes together in an array? I'm taking the output of an MD5 hash and would like to XOR every four bytes together so that I can get a 32 bit int out of it. I could easily do this with a loop, but I thought it was an interesting problem for LINQ.

public static byte[] CompressBytes(byte[] data, int length)
{
    byte[] buffer = new byte[length];
    for (int i = 0; i < data.Length; i++)
    {
        for (int j = 0; j < length; j++)
        {
            if (i * length + j >= data.Length)
                break;
            buffer[j] ^= data[i * length + j];
        }
    }
    return buffer;
}

Slightly off topic, but is this even a good idea? If I need a int, would I be better off with a different hash function, or should I just take the first 4 bytes of the MD5 because XORing them all wouldn't help any? Comments are welcome.


Solution

  • You can use the IEnumerable.Aggregate function (not actually LINQ, but most people refer to the LINQ-related extension methods as LINQ) to perform a custom aggregate. For example, you could compute the total XOR of a list of bytes like this:

    var xor = list.Aggregate((acc, val) => (byte)(acc ^ val));
    

    You can create a virtually unreadable chain of extension method calls to do what you're after:

    int integer = BitConverter.ToInt32(Enumerable.Range(0, 3).
                  Select(i => data.Skip(i * 4).Take(4).
                      Aggregate((acc, val) => (byte)(acc ^ val))).ToArray(), 0)