【问题标题】:How to add two arrays in a loop with unknown length如何在一个未知长度的循环中添加两个数组
【发布时间】:2013-09-23 09:03:09
【问题描述】:

我有一个测量仪器,可以创建指定时间的测量值。在此期间,我必须从内部存储器中获取测量值以防止溢出。 目前我有这个:

public int FetchDatalog(int Time_s, double Period, out int Count, ref double[] Results)
{
    Count = 0;


    try
    {
        DateTime timeout = DateTime.UtcNow.AddSeconds(Time_s);
        double[] values;

        while (DateTime.UtcNow < timeout)
        {

        values = //here is the command to tell the instrument to return 10 results
        Count = values.Count();
        Thread.Sleep(500);
        //HERE IS SOMETHING MISSING <-----
        }

    }
    return 0;
}

所以我有一个函数,它总是在一个循环中读取来自仪器的 10 个结果,直到指定的时间结束。在循环期间,必须合并读取的数据。

在箭头标记的位置,我现在需要将 10 个值合并在一起并最终在结果中返回所有合并值的东西。

如何在长度未知的情况下做到这一点?

(额外的问题是:10 个结果可以是“最多 10 个”结果。有时少于 10 个,所以如果需要只读取 1 个值,我也可以在这里更改,但这会使其变慢。

感谢大家的帮助


在此处添加评论以便阅读 - Sayse

我的意思是合并:

loop1: values[]=1,2,3,4,5,6,7,8,9,0; 
loop2: values[]=11,22,33,44,55,66,77,88,99,11 
loop3: values[]=111,222,333,444,555,666,777,888,999,111 

这三个值最终应该在参数结果中返回为

result[]=1,2,3,4,5,6,7,8,9,0,11,22,33,44,55,66,
     77,88,99,11,111,222,333,444,555,6‌​66,777,888,999,111

所以它们应该放在一起形成一个更大的数组。

【问题讨论】:

  • 合并它们是什么意思?求和,求平均,做一些其他复杂的计算,什么?
  • 您是否考虑过返回List&lt;double&gt; 的结果?所有这些与refout 参数混在一起的东西有点奇怪(你的参数名称也是如此)。
  • 离题说明:我认为Thread.Sleep 没有做任何有用的事情
  • 为什么不直接声明 List&lt;double&gt; 并在您的箭头位置执行 theList.AddRange(values);。然后,一旦循环结束,您就可以将所有结果放在一起。
  • 我的意思是合并:loop1: values[]=1,2,3,4,5,6,7,8,9,0; loop2: values[]=11,22,33,44,55,66,77,88,99,11 loop3: values[]=111,222,333,444,555,666,777,888,999,111 这三个值最终应该在参数结果中返回结果 []=1,2, 3,4,5,6,7,8,9,0,11,22,33,44,55,66,77,88,99,11,111,222,333,444,555,666,777,888,999,111 所以它们应该放在一个更大的数组中。

标签: c# arrays loops merge


【解决方案1】:

如果您出于某种原因需要将数组作为参数类型,您可以创建一个列表,附加到列表中,然后返回结果:

public int FetchDatalog(int Time_s, double Period, out int Count, ref double[] Results)
{
    Count = 0;
    List<double> existing = new List<double>(Results);

    try
    {
        DateTime timeout = DateTime.UtcNow.AddSeconds(Time_s);
        double[] values;    
        while (DateTime.UtcNow < timeout)
        {
            values = //here is the command to tell the instrument to return 10 results
            Count += values.Length;
            Thread.Sleep(500);

            existing.AddRange(values);
        }    
    }
    finally 
    {
        Results = existing.ToArray();        
    }

    return 0;
}

如果我有我的 druthers,它看起来更像:

public int FetchDatalog(int readLength, double sleepPeriod, List<double> results)
{
    var readingsCount = 0;
    try
    {
        var timeout = DateTime.UtcNow.AddSeconds(readLength);
        while (DateTime.UtcNow < timeout)
        {
            values = RetrieveBufferedSensorReadings(10);
            readingsCount += values.Length;
            results.AddRange(values);                
            Thread.Sleep(sleepPeriod);
        }
        return readingsCount;
    }
    catch (Exception e) //<-- this should be special purpose based on sleep/read failures
    {
       throw; //Return -1 or the like if you must... but ew.
    }
}

您甚至可以考虑在 4.0 中使用较新的 async 功能,因为 Thread.Sleep 通常被认为不好。

编辑:

根据您的上一条评论,您似乎正在这样做:

double[] Results = new double[100]; 
ret = GetData(TimeSec, out Count, ref Results);

我觉得这是一个糟糕的结构,但我们会用它作为学习工具:

public int GetData(int Time_s, out int Count, ref double[] Results)
{

    var lengthIncrement = 100;
    Count = 0;

    try
    {
        DateTime timeout = DateTime.UtcNow.AddSeconds(Time_s);
        double[] values;    
        while (DateTime.UtcNow < timeout)
        {
            values = //here is the command to tell the instrument to return 10 results

            //Before copying over value, make sure we won't overflow
            //If we will, extend array
            if (Count + values.Length > Results.Length) {
               var temp = new double[Results.Length + lengthIncrement];
               Array.Copy(Results, temp, Count);
               Results = temp;
            }                

            Array.Copy(values, 0, Results, Count, values.Length);
            Count += values.Length;
            Thread.Sleep(500);
        }    
    }

    return 0;
}

ideone example.

请允许我重申许多其他人所说的话...以下是更好的设计:

var results = new List<double>(); 
ret = GetData(TimeSec, out Count, results);

【讨论】:

  • 我会在 while 之前移动 existing 的实例化并在之后设置 Results 这样你就不会在每次迭代时都创建一个新的 List。
  • 感谢您提供代码示例。它工作得很好。 @Cemafor:你能描述一下我必须改变什么吗?谢谢
  • @ThomasMann,他已经将我的建议添加到他的代码中。我认为编辑很快就没有显示为答案的编辑。虽然,尝试最终接缝有点奇怪。 try 在原始代码中做了什么?
  • 他原始代码中的尝试没有做任何事情......我只是偷了它并使用 finally 来确保他的返回变量被更新。
  • 我的代码中有一个 try &catch 块。我没有把它插在这里以保持它的小。
猜你喜欢
  • 2021-10-25
  • 1970-01-01
  • 1970-01-01
  • 2014-01-07
  • 1970-01-01
  • 1970-01-01
  • 2020-05-04
  • 1970-01-01
  • 2018-04-10
相关资源
最近更新 更多