2016-05-02 112 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; 
    } 
}