实现不同类型数组的更好的方法 [英] A better way to implement collection of array of different types

查看:174
本文介绍了实现不同类型数组的更好的方法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在C#中寻找一个半通用的数据结构来存储不同的整型和浮点型数组。在某些情况下,整数是位字段,其中每个位同样重要,并且精度损失是不允许的。我发现这个困难和凌乱,因为C#类型的系统和我缺乏C#流利。



项目:Ethercat周期性数据包到达并转换为结构(Packet)并累积为 Packet [] 在实验过程中。数据包的每个字段从 Packet [] 转换为数组。



我相信我正在寻找一种方法来将这些数组'包装成一个类型,以便它们可以作为集合的一部分。包装它们还具有一些其他优点(命名,SI比例因子的硬件等),以便于将硬件与稍后的实现分离。



我最好的包装器被称为DataWrapper(下面简化了),但是我在存储,精度损失,对象和数量的使用方面做了不舒服的妥协的代码。



C#中是否有更好的方式?我的黄金标准是在Python中使用列表或numpy.arrays列表显而易见的实现方式。



可以使用对象吗?怎么样?是否可以对整个数组进行包装,或者每个数组元素是否单独包装(低效)?



我已经看到多个数据类型的列表?然而,似乎很多代码和高级编程技术基本上是List List。

  public class DataWrapper 
{
private double [] double_array; //用双引号,但是如果我不使用float
私有字符串名称,
private double scale_factor_to_SI;

public DataWrapper(string name,double scale_factor,dynamic dynamic_array)
{

this.name = name;
this.scale_factor_to_SI = scale_factor;
this.double_array = new double [dynamic_array.Length];

for(int cnt = 0; cnt< dynamic_array.Length; cnt ++)
{
this.double_array [cnt] =(double)dynamic_array [cnt]
}
}

public void Get(out int [] i_array)
{
i_array = this.double_array.Select(item => int)item).ToArray();
}

public void Get(out long [] i_array)
{
i_array = this.double_array.Select(item =>(long)item)。 ToArray();
}

public double [] GetSI()
{
return this.double_array.Select(item => this.scale_factor_to_SI *(double)item)。 ToArray();
}
}

public struct Packet //这是一个示例数据包 - 实际数据包大得多,随时间而变化。我希望在1个地方不要变更。
{
public long time_uS;公共Int16速度

public UInt32 status_word;
};

public class example
{
public Packet [] GetArrayofPacketFromHardware()
{
return null;
}

public example(){
Packet [] array_of_packet = GetArrayofPacketFromHardware();

var time_uS = array_of_packet.Select(p => p.time_uS).ToArray();
var velocity = array_of_packet.Select(p => p.velocity).ToArray();
var status_bits = array_of_packet.Select(p => p.status_word).ToArray();

列表< DataWrapper> collection = new List< DataWrapper> {};
collection.Add(new DataWrapper(time,1.0e-6,time_uS));
collection.Add(new DataWrapper(velocity,1/8192,velocity));
collection.Add(new DataWrapper(status,1,status_bits));
}
}


解决方案

回答C#有更好的方法吗? - 是的。



使用列表<动态> 作为数组的集合。

 列表<动态> array_list = new List< dynamic> {}; 
public void AddArray(dynamic dynamic_array)
{
this.array_list.Add(dynamic_array);
}

当然,任何东西都可以传递给它 - 但可以测试。



列表<动态> 在这种情况下比 ArrayList 当尝试索引从列表获取的数组时,IDE标记错误。

  int ndx = 0; 
foreach(this.array_list中的var array_from_list){
var v = array_from_list [ndx]; //如果array_from_list是ArrayList
}

完整的例子如下(但仅在概念上复制我的以上包装)。

  using System; 
使用System.Collections.Generic;


命名空间应用程序
{
class MyTest
{
列表<动态> array_list = new List< dynamic> {};
int length;

public void AddArray(dynamic dynamic_array)
{
this.array_list.Add(dynamic_array);
this.length = dynamic_array.Length;
}
public dynamic GetVector(int ndx)
{
return array_list [ndx];
}
public void Display()
{
for(int ndx = 0; ndx< this.length; ndx ++)
{
string ln_txt =;
foreach(this.array_list中的var array_from_list)
{
string s = array_from_list [ndx] .ToString();
ln_txt + = ${s};
}

Console.WriteLine(ln_txt);
}

}
}

静态类程序
{


[STAThread]
static void Main(string [] args)
{

MyTest test = new MyTest();
test.AddArray(new long [] {10,20,30,40});
test.AddArray(new int [] {1,2,3,4});
test.AddArray(new double [] {.1,.2,.3,.4});
test.AddArray(new string [] {a,b,c,d});
test.Display(); (int vecnum = 0; vecnum< 4; vecnum ++)



$ b {
var vector = test.GetVector(vecnum);
Console.Write($vnum:{vecnum}:);

foreach(矢量中的var值)
{
Console.Write(${value});
}
Console.WriteLine();
}

}
}
}

我了解到 http://stackoverflow.com/a/10380448/4462371 可能更正确技术说明。


I'm looking for a semi-general purpose data structure in C# to store arrays of different integer and float types. In some cases, the integers are bit fields where each bit is equally important and loss of precision isn't tolerable. I'm finding this difficult and messy because of the C# type system and my lack of C# fluency.

The project: Ethercat periodic packets arrive and are converted to a structure (Packet) and accumulated as Packet[] over the course of an experiment. Each field of Packet from Packet[] is converted into an array.

I believe I'm looking for a way to 'wrap' these arrays into a single type so they can be part of a collection. Wrapping them has some other advantages (naming, hardware to SI scale factors, etc) to facilitate decoupling the hardware from the later implementation.

My best 'wrapper' is called 'DataWrapper' (simplified below) but with it I've made uncomfortable compromises in storage, loss of precision, use of object and quantity of code.

Is there a 'better' way in C#? My gold standard is the apparently trivial implementation without obvious compromises in Python using list of lists or numpy.arrays.

Could 'object' be used? How? Is it possible to box the whole array or must each array element boxed individually (inefficient)?

I've seen A list of multiple data types? however, seems like a lot of code and advanced programming techniques for what is essentially a List of List.

public class DataWrapper
{
    private double[] double_array;  // backing with double, but it could if I don't use float 
    private string name;
    private double scale_factor_to_SI;

    public DataWrapper(string name, double scale_factor, dynamic dynamic_array)
    {

        this.name = name;
        this.scale_factor_to_SI = scale_factor;
        this.double_array = new double[dynamic_array.Length];

        for (int cnt = 0; cnt < dynamic_array.Length; cnt++)
        {
            this.double_array[cnt] = (double)dynamic_array[cnt];
        }
    }

    public void Get(out int[] i_array)
    {
        i_array = this.double_array.Select(item => (int)item).ToArray();
    }

    public void Get(out long[] i_array)
    {
        i_array = this.double_array.Select(item => (long)item).ToArray();
    }

    public double[] GetSI()
    {
        return this.double_array.Select(item => this.scale_factor_to_SI * (double)item).ToArray();
    }
}

public struct Packet  // this is an example packet - the actual packet is much larger and will change over time.  I wish to make the change in 1 place not many.
{
    public long time_uS;
    public Int16 velocity;
    public UInt32 status_word;
};

public class example
{
    public Packet[] GetArrayofPacketFromHardware()
    {
        return null;
    }

    public example() {
        Packet[] array_of_packet = GetArrayofPacketFromHardware();

        var time_uS = array_of_packet.Select(p => p.time_uS).ToArray();
        var velocity = array_of_packet.Select(p => p.velocity).ToArray();
        var status_bits = array_of_packet.Select(p => p.status_word).ToArray();

        List<DataWrapper> collection = new List<DataWrapper> { };
        collection.Add(new DataWrapper("time", 1.0e-6, time_uS));
        collection.Add(new DataWrapper("velocity", 1/8192, velocity));
        collection.Add(new DataWrapper("status", 1, status_bits));  
    }
}

解决方案

The answer to "Is there a better way in C#?" - is yes.

Use List<dynamic> as the collection for your arrays.

List<dynamic> array_list = new List<dynamic> { };
public void AddArray(dynamic dynamic_array)
{
   this.array_list.Add(dynamic_array);
}

Of course anything could be passed into it - but that can be tested for.

List<dynamic> is better in this situation than ArrayList as when attempting to index an array taken from 'list' the IDE flags an error.

int ndx = 0;
foreach (var array_from_list in this.array_list) {                
  var v = array_from_list[ndx];  // error if array_from_list is ArrayList
}

A complete illustration follows (but it only conceptually replicates my above wrapper).

using System;
using System.Collections.Generic;


namespace Application
{
    class MyTest
    {
        List<dynamic> array_list = new List<dynamic> { };
        int length;

        public void AddArray(dynamic dynamic_array)
        {
            this.array_list.Add(dynamic_array);
            this.length = dynamic_array.Length;
        }
        public dynamic GetVector(int ndx)
        {
            return array_list[ndx];
        }
        public void Display()
        {
            for (int ndx = 0; ndx < this.length; ndx++)
            {
                string ln_txt = "";
                foreach (var array_from_list in this.array_list)
                {
                    string s = array_from_list[ndx].ToString();
                    ln_txt += $"{s} ";
                }

                Console.WriteLine(ln_txt);
            }

        }
    }

    static class Program
    {


        [STAThread]
        static void Main(string[] args)
        {

            MyTest test = new MyTest();
            test.AddArray(new long[] { 10, 20, 30, 40 });
            test.AddArray(new int[] { 1, 2, 3, 4 });
            test.AddArray(new double[] { .1, .2, .3, .4 });
            test.AddArray(new string[] { "a", "b", "c", "d" });
            test.Display();


            for (int vecnum = 0; vecnum < 4; vecnum++)
            {
                var vector = test.GetVector(vecnum);
                Console.Write($"vnum:{vecnum} :   ");

                foreach (var value in vector)
                {
                    Console.Write($"{value}   ");
                }
                Console.WriteLine("");
            }

        }
    }
}

I've since learned that http://stackoverflow.com/a/10380448/4462371 is probably more correct technical explanation.

这篇关于实现不同类型数组的更好的方法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆