gpt4 book ai didi

c# - 持续保存数据

转载 作者:行者123 更新时间:2023-11-30 22:00:09 24 4
gpt4 key购买 nike

我有一个物体随时间在空间中移动,我想每 0.5 秒保存一次它的位置 (x, y, z),总共保存 10 秒。该对象将不断移动,但我只想要它最近的 10 秒。

我一直在考虑使用数组[20],但这意味着我必须每隔 0.5 秒弹出最后一个元素(比如数据 [19]),将之前的每个元素压入并在数据处添加当前元素[0].

有没有更优雅的方法来做到这一点?

编辑:性能可能是个问题,因为我将保存大量这些对象的数据。这就是为什么我正在寻找一种聪明的方法来做到这一点。提前致谢:)

最佳答案

如评论中所述,您可以使用 Circular Buffer .

这是一个示例实现。

/// <summary>
/// A circular buffer with a maximum capacity set at construction time.
/// You can repeatedly add elements to this buffer; once it has reached its capacity
/// the oldest elements in it will be overwritten with the newly added ones.
/// This is how it differs from a queue: Oldest elements will be overwritten when the buffer is full.
/// </summary>
/// <typeparam name="T">The type of the elements stored in the buffer.</typeparam>

[SuppressMessage("Microsoft.Naming", "CA1710:IdentifiersShouldHaveCorrectSuffix", Justification = "Calling this CircularBufferCollection would be stupid.")]

public class CircularBuffer<T>: IEnumerable<T>
{
/// <summary>Constructor.</summary>
/// <param name="capacity">The maximum capacity of the buffer.</param>

public CircularBuffer(int capacity)
{
Contract.Requires<ArgumentOutOfRangeException>(capacity > 0, "Capacity must be greater than zero.");

// We will use a buffer with a size one greater than the capacity.
// The reason for this is to simplify the logic - we can use "front == back" to indicate an empty buffer.

_buffer = new T[capacity+1];
}

/// <summary>The buffer capacity.</summary>

public int Capacity
{
get
{
Contract.Ensures(Contract.Result<int>() > 0);
return _buffer.Length - 1;
}
}

/// <summary>The number of elements currently stored in the buffer.</summary>

public int Count
{
get
{
Contract.Ensures(0 <= Contract.Result<int>() && Contract.Result<int>() <= this.Capacity);

int result = _back - _front;

if (result < 0)
{
result += _buffer.Length;
}

return result;
}
}

/// <summary>Is the buffer empty?</summary>

public bool IsEmpty
{
get
{
return this.Count == 0;
}
}

/// <summary>Is the buffer full? (i.e. has it reached its capacity?)</summary>

public bool IsFull
{
get
{
return nextSlot(_back) == _front;
}
}

/// <summary>Empties the buffer.</summary>

public void Empty()
{
Contract.Ensures(this.IsEmpty);

_front = _back = 0;
Array.Clear(_buffer, 0, _buffer.Length); // Destroy any old references so they can be GCed.
}

/// <summary>Add an element to the buffer, overwriting the oldest element if the buffer is full.</summary>
/// <param name="newItem">The element to add.</param>

public void Add(T newItem)
{
_buffer[_back] = newItem;
_back = nextSlot(_back);

if (_back == _front) // Buffer is full?
{
_front = nextSlot(_front); // Bump the front, overwriting the current front.
_buffer[_back] = default(T); // Remove the old front value.
}
}

/// <summary>Removes and returns the oldest element from the buffer.</summary>
/// <returns>The element that was removed from the buffer.</returns>
/// <exception cref="InvalidOperationException">Thrown if the buffer is empty.</exception>

public T RemoveOldestElement()
{
Contract.Requires<InvalidOperationException>(!this.IsEmpty, "Cannot remove an element from an empty buffer.");

T result = _buffer[_front];
_buffer[_front] = default(T); // Zap the front element.
_front = nextSlot(_front);

return result;
}

/// <summary>
/// The typesafe enumerator. Elements are returned in oldest to newest order.
/// This is not threadsafe, so if you are enumerating the buffer while another thread is changing it you will run
/// into threading problems. Therefore you must use your own locking scheme to avoid the problem.
/// </summary>

public IEnumerator<T> GetEnumerator()
{
for (int i = _front; i != _back; i = nextSlot(i))
{
yield return _buffer[i];
}
}

/// <summary>The non-typesafe enumerator.</summary>

IEnumerator IEnumerable.GetEnumerator()
{
return GetEnumerator(); // Implement in terms of the typesafe enumerator.
}
/// <summary>Calculates the index of the slot following the specified one, wrapping if necessary.</summary>

private int nextSlot(int slot)
{
return (slot + 1) % _buffer.Length;
}

/// <summary>
/// The index of the element at the front of the buffer.
/// If this equals _back, the buffer is empty.
/// </summary>

private int _front;

/// <summary>
/// The index of the first element BEYOND the last used element of the buffer.
/// Therefore this indicates where the next added element will go.
/// </summary>

private int _back;

/// <summary>The underlying buffer. This has a length one greater than the actual capacity.</summary>

private readonly T[] _buffer;
}

关于c# - 持续保存数据,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28762630/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com