2016-05-02 152 views
0

我正在创建一个应用程序,其工作是生成两个列表并按需显示它们。以及每秒钟更新值。替换列表中最古老的值?

我需要以这种方式更新列表,以便列表中最老的值先被替换。我会怎么做?下面是我的代码当前状态。

using System; 
using System.Collections.Generic; 
using System.Linq; 
using System.Text; 
using System.Threading.Tasks; 

namespace Data_Collector 
{ 
    //What is needed? 
    //Need to generate a list of both metric values, and imperial values. 
    //Need to be able to display a list 

    public class IMeasuringDevice_Helper 
    { 
     private int limit; //Limits the list size. 
     private float RNDouble; 

     public void MetricValueGenerator() 
     { 

      limit = limit + 1; 
      Console.WriteLine("Limit Level = " + limit); 


      if (limit <= 10) 
      { 
       List<float> MetricValueGenerated = new List<float>(); 

       Random rnd = new Random(); 
       float rndINT = rnd.Next(1, 10); 
       RNDouble = rndINT/10; 
       Console.WriteLine(RNDouble); 
       MetricValueGenerated.Add(RNDouble); 
      } 
      else 
      { 
       Console.WriteLine("limit reached"); 
      } 

     } 

     public void ImperialValueGenerator() 
     { 
      //TODO 
     } 

    } 
} 
+2

听起来像你需要一个FIFO数据结构或一个循环队列。 –

+0

正如@ Pierre-LucPineault所提到的,FIFO结构是有意义的,比如[queue](https://msdn.microsoft.com/en-us/library/7977ey2c(v = vs.110).aspx) – Rob

回答

1

对此,您将需要Queue,但您需要对其进行扩展。默认的C#队列是先进先出(完全是你想要的语义),但是不会限制你的代码当前处理它们的方式。如果已满,它只是通过增长因子增长。

因此,您需要扩展Queue对象并覆盖Enqueue方法以执行所需操作。它可能会看起来有点像这样:

public class BoundedQueue<T> : Queue<T> 
{ 
    private readonly int _bound; 

    public BoundedQueue(int bound) 
    { 
     _bound = bound; 
    } 

    public new void Enqueue(T item) 
    { 
     if(Count >= _bound) 
     { 
      throw new IndexOutOfRangeException("limit reached"); 
      // If simply throwing an exception isn't cool, you can also do the following to pop off the oldest item: 
      // base.Dequeue(); 
     } 
     base.Enqueue(item); 
    } 
} 

要注意的是,你把它变成一些其他类型的对象显示的时候,你可以看到它在你所期望的相反顺序,作为唯一最旧的项目将位于队列的“顶部”。您只需调用与大多数支持LINQ的对象配合使用的Reverse()方法即可对此进行分类。

+0

上面应该可以正常工作,但我现在正好远离我的开发环境,无法检查以确保它编译。如果有某种语法错误或其他问题,请提醒我,我会很乐意更新我的答案! – tmesser

+0

如果你创建一个由'ConcurrentQueue'支持的'BlockingCollection',你可以设置最大大小,那么在.NET中有一个有限大小的队列。 –

+0

我喜欢你使用的方法(它似乎是迄今为止最流行的方法),但是有没有其他方法可以做我正在寻找的?我觉得Quque对我的目的有点矫枉过正。我也尝试了你的代码,它给了[大量的错误](http://pastebin.com/QdQjzTx8)(但你可能在移动,所以我感到你的痛苦:P)。 – Sie

0

如果你不想做任何类扩展为@YYY曾建议,几乎与Queue取代List,与.Enqueue()和替代oldestValue = yourList[oldestIndex]使用oldestValue = yourQueue.Dequeue()更换.add()

从你的问题

除此之外,您的变量应该用小写字母开头,并且RNDouble = rndINT/10;将要结束了= 0的大部分时间,因为你应该为10.0而不是10

好划分,所以我很无聊...(我也不会用这种方法,但我猜你正在学习,并没有教过队列,所以这可能有助于列表):

public class MeasuringDevice_Helper 
{ 
    private const int LIMIT = 10; // This is a constant value, so should be defined IN_CAPS in class definition 
    List<double> metricValues = new List<double>(LIMIT); // This needs to be at class level so it doesn't get lost 
    Random rnd = new Random(); // This is used frequently so define at class level 

    public void GenerateMetricValue() // This is now named like the action it performs 
    { 
     Console.WriteLine("Current metric values = " + metricValues.Count); 

     if (metricValues.Count < LIMIT)  // This should just be < not <= 
     { 
      float rndInt = rnd.Next(1, 10); 
      double rndDouble = rndInt/10.0; // An Int divided by Int will = Int 
      Console.WriteLine("Added " + rndDouble); 
      metricValues.Add(rndDouble); 
     } 
     else 
     { 
      Console.WriteLine("limit reached"); 
     } 
    } 

    public double PopOldestMetricValue() 
    { 
     double value = metricValues[0]; 
     metricValues.RemoveAt(0); 
     return value; 
    } 
}