我正在创建一个应用程序,其作用是生成两个列表并按需显示它们。以及每秒更新值。
我需要以这样的方式更新列表,以便首先替换列表中最旧的值。我该怎么办?以下是我当前状态的代码。
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
}
}
}
答案 0 :(得分:1)
此处需要Queue,但您需要对其进行扩展。默认的C#Queue是First-In,First-Out(完全是您想要的语义),但不会订阅限制代码当前处理它们的方式。如果充满,它只会增长一个增长因素。
因此,您需要扩展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()
方法即可对其进行排序。
答案 1 :(得分:0)
如果您不想像@YYY所建议的那样进行任何类扩展,请将List
替换为Queue
,将.add()
替换为.Enqueue()
,而不是oldestValue = yourList[oldestIndex]
使用oldestValue = yourQueue.Dequeue()
。
除了你的问题,你的变量应该以小写字母开头,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;
}
}