是否可以在数组中存储一组滚动值而不超过设置索引?
例如,我将基本的控制台示例放在一起,如下所示:
static void Main(string[] args)
{
int[] myvalue;
myvalue = new int[10];
for (int i = 0; i < 20; i++)
{
Console.WriteLine("Array {0} is {1}", i, myvalue[i]);
}
Console.ReadLine();
}
在当前的方法中,我获得了一个超出范围的索引异常。我想要做的是将数组限制为10个项目,但随着计数的增加,用新值覆盖现有项目。因此,我可以迭代100次,但数组只会在例程结束时显示最后十个值(89-99)。
如果数组不是最佳方法,我欢迎任何有关如何将其存储在内存中的建议。
谢谢
答案 0 :(得分:6)
您可以使用List来存储值,然后包装Add方法来处理项目数量的限制。这将为您处理所有“向下滑动”的逻辑。
const int MAX_ITEMS = 10;
List<int> list = new List<int>();
void AddItem(int k)
{
list.Add(k);
if (list.Count > MAX_ITEMS)
{
// discard the item at the front of the list
list.RemoveAt(0);
}
}
每当您想要添加值时,只需拨打AddItem(n)
,例如:
for (int i = 0; i < 100; i++)
{
AddItem(i);
}
每当您想要读出值时,您只需执行以下操作:
for (int i = 0; i < list.Count; i++)
{
Console.WriteLine(list[i]);
}
这也有一个优点,你可以放入少于最大数量的项目(比如你只有6而不是10)并且它仍然可以正常工作(你不必担心未填充的数组项目)。
答案 1 :(得分:6)
听起来像circular buffer。在codeplex上的C#中有一个existing implementation。
答案 2 :(得分:3)
如果您希望数组始终按照遇到的顺序保存最后十个值 ,那么每次将array[N]
复制到{时,您必须“向下滑动数值”数组{1}}所有N&gt; = 1,然后在最后一个位置写入“最新”值。
如果您不需要数组具有此特定顺序的值,则可以使用模数技巧并写入任何array[N-1]
的{{1}};一旦你到达终点,它就会“循环”到数组的开头。
最后,如果想要按顺序和的值,您需要一个不会强制您复制每次迭代的所有元素的数据结构,您可以使用:
答案 3 :(得分:1)
您可以使用循环链接列表而不是数组。
在下面的代码段中,currentNode始终是输入的最后一个节点。这样,当您按照链接列表进行完整循环时,您可以使列表任意长,并且永远不必担心结束的位置,因为在某些时候您会自动开始覆盖旧值。
static void Main(string[] args)
{
//create first node
var firstNode = new Node();
var lastNode = firstNode;
//create linked list
for(int i=0; i<9; i++)
{
var nextNode = new Node();
lastNode.nextNode = nextNode;
lastNode = nextNode;
}
//link tail of list to beginning to make the circular reference.
lastNode.nextNode = firstNode;
var currentNode = firstNode;
//your code goes here
for(int j=0; j<1000; j++)
{
currentNode.value = j; //now you set your values in your loop
currentNode = currentNode.nextNode; //and move on to the next node
}
}
public class Node
{
public int value;
public Node nextNode;
}
答案 4 :(得分:0)
你可以这样试试:
myvalue = new int[10];
for (int i = 0; i < 100; i++)
myvalue[i % myvalue.Length] = i;
当然,这将从头到尾开始,因此数组可能不是您将值写入其中的顺序,而是有些旋转。如果您想避免这种情况,则需要将元素从myvalue[1]
复制到myvalue[myvalue.Length-1]
到myvalue[1]
到myvalue[myvalue.Length-2]
,并在每次插入新元素时覆盖myvalue[myvalue.Length-1]
。或者,您可以在完成所有插入后旋转阵列以固定定位。
答案 5 :(得分:0)
这可能不是最优雅的代码,但它说明了如何创建一个记录n个最新值的循环缓冲区:
const int SIZE = 10;
int[] myValue = new int[SIZE];
int start = 0;
int count = 0;
void NewValue(int v)
{
myValue[start] = v;
if (count < SIZE)
count++;
start = (++start) % SIZE;
}
void ListValues()
{
for (int i = start - 1; i >= 0; i--)
Console.WriteLine(myValue[i]);
if (count >= SIZE)
for (int i = SIZE - 1; i >= start; i--)
Console.WriteLine(myValue[i]);
Console.WriteLine();
}
private void Test()
{
for (int i = 0; i < 20; i++)
{
NewValue(i);
ListValues();
}
}