【问题标题】:Dictionary with limited size that removes oldest elements?删除最旧元素的大小有限的字典?
【发布时间】:2013-04-02 00:18:54
【问题描述】:

是否存在可用于散列数据的现有数据结构,可以删除最旧的元素?

我现在正在考虑的方法是让一个字典和一个队列使用字典进行快速查找,并能够使用队列从字典中删除最旧的元素。

【问题讨论】:

  • 您是否需要删除最旧的元素以外的元素?您是否需要存储大量元素 - 换句话说,此类删除的性能有多重要?
  • 这个潜在集合要存储什么类型的数据..?
  • 要删除最旧的元素,您需要设置大小或时间...
  • 您可能需要一个循环缓冲区。也许看到stackoverflow.com/questions/590069/…
  • OrderedDictionary 在这里有用吗? msdn.microsoft.com/en-us/library/ms132577.aspx

标签: c# data-structures


【解决方案1】:

您可以使用OrderedDictionary。这将保持插入顺序(不像SortedDictionary,它将按键排序)。然后,您可以删除第一个被认为是最旧的可用元素。

【讨论】:

  • +1。请注意,删除第一个元素是 O(n),这可能没问题,因为问题没有指定该操作的任何时间要求。
  • @AlexeiLevenkov - 好点。同样对于 OP,如果优化是关键,那么使用 dotnetperls.com/dictionary-optimization 初始化 OrderedDictionary 可能值得测试容量大小(尽管本文与标准 Dictionary 集合相关,但原则仍应适用)
【解决方案2】:

OrderedDictionary 是一个很好的建议,但如果您需要字典中的字符串以外的类型,请尝试此方法;

public sealed class SizedDictionary<TKey, TValue> : Dictionary<TKey, TValue> {

private int maxSize;
private Queue<TKey> keys;

public SizedDictionary(int size) {
    maxSize = size;
    keys = new Queue<TKey>();
}

new public void Add (TKey key, TValue value) {
    if (key==null) throw new ArgumentNullException();
    base.Add(key, value);
    keys.Enqueue(key);
    if (keys.Count > maxSize) base.Remove(keys.Dequeue());
}

new public bool Remove (TKey key) {
    if (key==null) throw new ArgumentNullException();
    if (!keys.Contains(key)) return false;
    var newQueue = new Queue<TKey>();
    while (keys.Count>0) {
        var thisKey = keys.Dequeue();
        if (!thisKey.Equals(key)) newQueue.Enqueue(thisKey);
    }
    keys=newQueue;
    return base.Remove(key);
}
}

我正在使用密封类,因为我们只是隐藏了添加和删除方法,所以如果要继承这个类,则不清楚使用的是哪个版本。更完整的解决方案是使用内部字典而不是继承,但这会更加冗长

【讨论】:

    【解决方案3】:

    System.Collections.Generic.SortedList 只是一个按键排序的字典。如果键在某种程度上是临时的,您可以简单地使用RemoveAt 在达到一定大小时删除第一个元素,然后再添加另一个条目。

    很可能,既然您提到了Dictionary,您可能没有临时密钥。但是,Dictionary 只是 KeyValuePair&lt;K,V&gt; 对象的集合。因此,您可以有一个排序列表,其中值为 KeyValuePair&lt;K,V&gt;,键是添加元素的日期/时间。

    【讨论】:

      【解决方案4】:

      由于您有特定要求,我将实施 后面带有队列/缓冲区的字典(例如 cmets 中提到的循环缓冲区)。

      OrderedDictionary 是一个不错的选择,也是如何做到这一点的一个很好的来源(我不想在这里发布它,但你可以很容易地找到它)——你只需要比 ArrayList 更好的东西来保存你的元素(并且做出队)-因为您不断删除“第一个”。

      【讨论】:

      • 一个很好的来源(我不想在这里发布,但你可以很容易地找到它)”——有没有具体的秘密了解OrderedDictionarys 的来源我应该在这里寻找?
      • @ruffin 我的意思是去谷歌(或duckduckgo :)“OrderedDictionary 源代码”或类似的东西。如果我没记错的话(很多年前),实际的 OrderedDictionary 实现可以向您展示如何为特定目的创建自己的特定字典。我不想发布链接,因为当时 .NET 是封闭源代码。
      • 明白了。很困惑为什么你需要一个 as if MS' was broken 的“好来源”,但你的字面意思是 get some good source [code] for one。谢谢!
      猜你喜欢
      • 2010-12-17
      • 2015-03-16
      • 1970-01-01
      • 1970-01-01
      • 2011-12-24
      • 1970-01-01
      • 2013-06-15
      • 2012-02-12
      • 1970-01-01
      相关资源
      最近更新 更多