我有一个每10分钟添加一次KeyValuePair的SortedList。我正在尝试保留最新的 10 个 KeyValuePair 并删除所有以前的对,但我正在做的事情不起作用。下面我附上了我的代码,并在每个步骤中进行了解释。任何帮助将不胜感激。
private SortedList<int, double> myList = new SortedList<int, double>();
// Every 10 minutes a new KeyValuePair is added to myList so
// I have no issue with sorting. I'm only trying to get the most
// recent 10 KeyValuePairs.
// My Attempt (the only one that worked without errors)
int mylistCount = 10;
if (myList.Count()>mylistCount)
{myList.Clear();}
// The issue with my attempt is that it erases the entire myList
// As a result, whenever myList reaches 10, it goes back to Zero.
// What I'm trying to do is keep myList Count at 10 containing only
// the most recent KeyValuePairs.
**在myList中,Key int是PlayerID#(随机的(,值是玩家的得分%
要回答您的问题:
- 排序不是当前设置的问题。
- 它不一定是排序列表,我愿意接受任何建议。我只是更熟悉使用字典和列表。
- 我从未使用过队列,但愿意尝试。(将不得不研究,我每天都在学习新东西(
- 没有时间戳,新条目的时间并不重要。我要做的就是确保myList只有最近的10个。
我试图做的是将 myList 计数保持在 10 只包含 最新的键值对。
您想保留最近的 10 对,所以我假设排序是按加法时间进行的。如果这是真的,则无需对它们进行排序,因此不需要SortedList
。您可以按照评论中的建议使用Queue
。
队列是先进先出 (FIFO(。这意味着您知道队列中的第一个元素是最古老的,并且当第十一个元素进入时需要取消排队。例如,这难道不能用很少的仪式来解决问题吗?
// q is a Queue (FIFO)
if (q.Count == 10)
{
// we've reached our cap, remove the element at the
// front of the q (the oldest one)
q.Dequeue();
}
// we'll always add the newest element to the end of the q
q.Enqueue(new KeyValuePair<int, double>(key, value));
使用LinkedList而不是SortedList怎么样?
if(myLinkedList.Count() > 10)
myLinkedList.RemoveFirst();
这将始终删除列表中第一个添加的项目。
在不太了解密钥的情况下,我提供了一个简单的解决方案:
创建一个类来表示值及其添加时间,并实现IComparable<T>
接口:
public class TimeStampedDouble : IComparable<TimeStampedDouble>
{
public TimeStampedDouble(double value)
{
Value = value;
Date = DateTime.Now;
}
public double Value { get; private set; }
public DateTime Date { get; private set; }
public int CompareTo(TimeStampedDouble other)
{
return this.Date.CompareTo(other.Date);
}
// User-defined conversion to double, for convenience
public static implicit operator double(TimeStampedDouble d)
{
return d.Value;
}
}
更改列表以改为存储此类型:
SortedList<int, TimeStampedDouble> list = new SortedList<int, TimeStampedDouble>();
使用新类将项目添加到列表中:
//In this line, 1 is the key, 6 is the double you are storing.
myList.Add(1, new TimeStampedDouble(6));
myList.Add(3, new TimeStampedDouble(5));
myList.Add(2, new TimeStampedDouble(4));
myList.Add(7, new TimeStampedDouble(3));
myList.Add(5, new TimeStampedDouble(2));
现在,您可以使用 Linq 获取最旧的项并将其删除:
if (myList.Count() > mylistCount)
{
var oldest = myList.OrderByDescending(i => i.Value).FirstOrDefault();
myList.Remove(oldest.Key);
}
具有键5
的项目将被删除。
没有必要检查oldest
是否null
,因为 a( 它是一种值类型和 b( 检查了最小数量的项目,因此假设列表将始终至少有一个项目,前提是mylistCount
大于 0
。
由于提供了到 double
的隐式转换,因此可以在不显式强制转换的情况下使用该值:
double doubleValue = myList[7];
我认为最方便的解决方案是使用有界列表,以确保列表中的元素永远不会超过最大计数。实施这样的列表并不是很困难。可能最灵活的方法是实现IDictionary<TKey, TValue>
接口,将工作委托给内部SortedList<TKey, TValue>
。波纹管是一种基于继承的方法,需要更少的代码。每当添加的元素导致Count
大于boundedCapacity
时,列表中最早的元素就会自动删除。
public class BoundedSortedList<TKey, TValue> : SortedList<TKey, TValue>
{
private readonly int _boundedCapacity;
private readonly List<TKey> _queue = new List<TKey>();
public BoundedSortedList(int boundedCapacity)
{
_boundedCapacity = boundedCapacity;
}
public new void Add(TKey key, TValue value)
{
base.Add(key, value);
_queue.Add(key);
if (this.Count > _boundedCapacity)
{
var keyToRemove = _queue[0];
this.Remove(keyToRemove);
}
}
public new TValue this[TKey key]
{
get { return base[key]; }
set { this.Remove(key); this.Add(key, value); }
}
public new bool Remove(TKey key) { _queue.Remove(key); return base.Remove(key); }
public new bool RemoveAt(int index) => throw new NotImplementedException();
public new void Clear() { base.Clear(); _queue.Clear(); }
}
使用示例:
var myList = new BoundedSortedList<int, double>(10);
不正确的使用示例:
var myIList = (IDictionary<int, double>)myList;
这将不起作用,因为通过接口访问类将绕过使列表有界的逻辑。
以下是对我有用的方法:
if (myList.Count()>mylistCount)
{myList.Remove(myList.FirstOrDefault());}
谢谢大家