Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to cleverly create an anonymous type from an IEnumerable<T>?

I would like to use LINQ to solve the following problem, I have the following collection:

List<byte> byteList = new List<byte() { 0x01, 0x00, 0x01, 0x02, 0x01, 0x00, 0x3, 0x4, 0x02 };

The data in this example follows the following pattern:

byteList[0] = address (1, 2, 3, ... n)

byteList[1] = old state, which is basically representative of an enum

byteList[2] = new state, same as above

I am interfacing with an embedded device and this is how I can view changes in inputs.

In order to clean up code and make it easier for a maintenance programmer to follow my logic, I'd like to abstract away some of the nuts and bolts involved and extract each three-byte set of data into an anonymous type to be used within the function to perform some additional processing. I've written a quick implementation, but I'm sure it can be greatly simplified. I'm trying to clean up the code, not muddy the waters! There has to be a simpler way to do the following:

List<byte> byteList = new List<byte>()
{
    0x01, 0x09, 0x01, 0x02, 0x08, 0x02, 0x03, 0x07, 0x03
};
var addresses = byteList
    .Where((b, i) => i % 3 == 0)
    .ToList();
var oldValues = byteList
    .Where((b, i) => i % 3 == 1)
    .ToList();
var newValues = byteList
    .Where((b, i) => i % 3 == 2)
    .ToList();

var completeObjects = addresses
    .Select((address, index) => new 
    { 
        Address = address,
        OldValue = oldValues[index],
        NewValue = newValues[index]
    })
    .ToList();
foreach (var anonType in completeObjects)
{
    Console.WriteLine("Address: {0}\nOld Value: {1}\nNew Value: {2}\n",
        anonType.Address, anonType.OldValue, anonType.NewValue);
}
like image 912
Nate Avatar asked Feb 21 '23 01:02

Nate


1 Answers

You can use Enumerable.Range and a little math:

List<byte> byteList = new List<byte>()
{
    0x01, 0x09, 0x01, 0x02, 0x08, 0x02, 0x03, 0x07, 0x03
};
var completeObjects = Enumerable.Range(0, byteList.Count / 3).Select(index =>
    new
    {
        Address = byteList[index * 3],
        OldValue = byteList[index * 3 + 1],
        NewValue = byteList[index * 3 + 2],
    });

If the number of bytes is not a multiple of 3, the extra one or two bytes will be ignored.

like image 127
Michael Liu Avatar answered Feb 23 '23 20:02

Michael Liu