1

I'm starting with an IntPtr to structured data from a hardware source that sends periodic packets. A thread copies a packet from the Intptr buffer and places byte[] into a queue. Later the queue is read and byte[] is converted to a structure using this answer and becomes a collection (array) of type Packet.

struct Packet {
  long time;
  int field1;
  short field2;
}

Packet[] array_of_packet; 

Without duplicating the structure definition, I would like to use the data as if it was a structure of arrays.

struct ArrayOfPacket {
  long[] time;
  int[] field1;
  short[] field2;
}

ArrayOfPacket data;  

This format allows other functions use them as vectors:

Plot(data.time, data.field1);
pathfinder
  • 106
  • 1
  • 8
  • I lost! Anyways, it should be long[] time and not long time[] – S.N Sep 29 '16 at 18:37
  • Well, that's a completely different layout. You'll need to copy everything over manually, item by item. – Luaan Sep 29 '16 at 18:40
  • You really should look into creating [immutable structs](http://stackoverflow.com/questions/3751911/why-are-c-sharp-structs-immutable). – juharr Sep 29 '16 at 18:46

3 Answers3

3

If all you want is an easy way to transform to arrays, then just use LINQ:

Plot (array_of_packet.Select(p => p.time).ToArray(),
      array_of_packet.Select(p => p.field1).ToArray());

If you're looking for a magic way to rearrange the data in memory without the cost of copying, then you're out of luck. ;-)

Justin Grant
  • 44,807
  • 15
  • 124
  • 208
0

Pretty easy with Linq

data.time = array_of_packet.Select(p => p.time).ToArray();
data.field1 = array_of_packet.Select(p => p.field1).ToArray();
data.field2 = array_of_packet.Select(p => p.field2).ToArray();

Though you'll need to make the properties public

A more effecient solution might be

var time = new long[array_of_packet.Length];
var field1 = new int[array_of_packet.Length];
var field2 = new short[array_of_packet.Length];
for(int i = 0; i < array_of_packet.Length; i++)
{
    time[i] = array_of_paket[i].time;
    field1[i] = array_of_paket[i].field1;
    field2[i] = array_of_paket[i].field2;
}

data.time = time;
data.field1 = field1;
data.field2 = field2;
juharr
  • 31,741
  • 4
  • 58
  • 93
0

You could create a wrapper class that exposes an array-like accessor syntax:

class ArrayWrapper<T, TField>
{
    Func<T, TField> getField;
    T[] array;

    public ArrayWrapper(T[] array, Func<T, TField> getField)
    {
        this.array = array;
        this.getField = getField;
    }

    public TField this[int index]
    {
        get { return this.getField(this.array[index]);}
    }

}

Then, with a simple helper method like this:

ArrayWrapper<T, TField> Wrap<T, TField>(T[] array, Func<T, TField> getField)
{
    return new ArrayWrapper<T, TField>(array, getField);
}

You could create an object like this:

var data = new
{
    time = Wrap(array_of_packet, p => p.time),
    field1 = Wrap(array_of_packet, p => p.field1),
    field2 = Wrap(array_of_packet, p => p.field2)
};

... which could be used the way you want:

Plot(data.time, data.field1);

Depending on your specific needs, you could elaborate on this in a number of ways:

  • Make the class implement an interface like IList<TField> so that Plot() can be written in a way that's agnostic of the underlying type. (Arrays already implement IList<TField>.)
  • If performance is a high priority, rather than using a delegate (Func<,>), you could add where T is struct to the ArrayWrapper definition, and have the ArrayWrapper take a byte offset as its constructor parameter, and do some unsafe magic to access the field's data more quickly.
StriplingWarrior
  • 151,543
  • 27
  • 246
  • 315
  • 1
    When I asked the question - this is what I was looking for - – pathfinder Sep 29 '16 at 19:21
  • @brainfog: I thought it might be. I love LINQ, but it sounded like you were trying to avoid copying the data into multiple arrays. – StriplingWarrior Sep 29 '16 at 19:26
  • Initially I was thinking of it in a step-by-step way : 1) collect data 2) convert to struct and an array of them 3) transform to an structure of arrays without re-typing the original structure (since I have many of them and they could change later) – pathfinder Sep 30 '16 at 14:25