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);
3
  • I lost! Anyways, it should be long[] time and not long time[] Commented Sep 29, 2016 at 18:37
  • Well, that's a completely different layout. You'll need to copy everything over manually, item by item. Commented Sep 29, 2016 at 18:40
  • You really should look into creating immutable structs. Commented Sep 29, 2016 at 18:46

3 Answers 3

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

Sign up to request clarification or add additional context in comments.

Comments

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;

Comments

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.

3 Comments

When I asked the question - this is what I was looking for -
@brainfog: I thought it might be. I love LINQ, but it sounded like you were trying to avoid copying the data into multiple arrays.
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)

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.