Храните самые последние KeyValuePairs в SortedList - PullRequest
0 голосов
/ 21 июня 2019

У меня есть SortedList, который добавляет KeyValuePairs каждые 10 минут.Я пытаюсь сохранить последние 10 KeyValuePairs и удалить все предыдущие пары, но то, что я делаю, не работает.Ниже я приложил свой код с пояснениями на каждом шаге.Любая помощь будет принята с благодарностью.

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 ключом int является PlayerID # (который является случайным), а значение - это оценка игрока%

Чтобы ответить на ваши вопросы:

  • Сортировка не является проблемой с текущей настройкой.
  • Это не обязательно должен быть SortedList, я открыт для любых предложений.Я просто более знаком с использованием словарей и списков.
  • Я никогда не использовал Очередь, но был открыт для ее пробования.(Придется исследовать это, я узнаю что-то новое каждый день)
  • Нет отметок времени, и время новых записей не имеет значения.Все, что я пытаюсь сделать, это убедиться, что в myList есть только самые последние 10.

Ответы [ 5 ]

2 голосов
/ 22 июня 2019

Что я пытаюсь сделать, так это сохранить в myList Count значение 10, содержащее только самые последние значения KeyValuePairs.

Вы хотите сохранить 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));
1 голос
/ 22 июня 2019

Как насчет использования LinkedList вместо SortedList.

if(myLinkedList.Count() > 10)
    myLinkedList.RemoveFirst();

Это всегда удалит первый добавленный элемент списка.

1 голос
/ 21 июня 2019

Не зная много о ключе, я предлагаю простое решение:

Создайте класс для представления значения, а также времени его добавления и реализует интерфейс 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];
0 голосов
/ 23 июня 2019

Вот что у меня сработало:

if (myList.Count()>mylistCount)
{myList.Remove(myList.FirstOrDefault());}

Спасибо всем

0 голосов
/ 22 июня 2019

Я думаю, что наиболее удобным решением было бы использование ограниченного списка, чтобы гарантировать, что элементы в списке никогда не превысят максимальное число.Реализация такого списка не очень сложна.Вероятно, наиболее гибкий способ - реализовать интерфейс 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;

Это не будет работать, потому что доступ к классу через интерфейс будет обходить логику, которая делает список ограниченным.

...