我从一个IntPtr开始,从发送周期性数据包的硬件源中获取结构化数据。线程从Intptr缓冲区复制数据包并将byte []放入队列。稍后读取队列并使用this answer将byte []转换为结构,并成为Packet类型的集合(数组)。
struct Packet {
long time;
int field1;
short field2;
}
Packet[] array_of_packet;
不重复结构定义我想使用数据,好像它是一个数组结构。
struct ArrayOfPacket {
long[] time;
int[] field1;
short[] field2;
}
ArrayOfPacket data;
此格式允许其他函数将它们用作向量:
Plot(data.time, data.field1);
答案 0 :(得分:3)
如果您只想要转换为数组,那么只需使用LINQ:
Plot (array_of_packet.Select(p => p.time).ToArray(),
array_of_packet.Select(p => p.field1).ToArray());
如果你正在寻找一种神奇的方法来重新安排内存中的数据而不需要复制费用,那么你就不走运了。 ; - )
答案 1 :(得分:0)
使用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();
虽然您需要制作属性public
更有效的解决方案可能是
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;
答案 2 :(得分:0)
您可以创建一个包含类似于数组的访问器语法的包装类:
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]);}
}
}
然后,用这样一个简单的辅助方法:
ArrayWrapper<T, TField> Wrap<T, TField>(T[] array, Func<T, TField> getField)
{
return new ArrayWrapper<T, TField>(array, getField);
}
您可以创建一个这样的对象:
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)
};
...可以按照你想要的方式使用:
Plot(data.time, data.field1);
根据您的具体需求,您可以通过多种方式详细说明:
IList<TField>
的接口,以便Plot()
可以以与基础类型无关的方式编写。 (数组已实现IList<TField>
。)Func<,>
),则可以将where T is struct
添加到ArrayWrapper
定义,并让ArrayWrapper
获取字节偏移量作为其构造函数参数,并执行一些unsafe
魔法来更快地访问字段的数据。