Насколько эффективны IEnumerable.First и IEnumerable.Last?

Я хочу использовать System.Collections.Generic.Queue, но с одним отличием: я хочу, чтобы Queue.Peek возвращал последний вставленный элемент, а не первый. Я все еще хочу, чтобы элементы входили и выходили таким же образом.

Я думал об использовании Queue.Last() в качестве альтернативы Queue.Peek() (который, как я полагаю, в основном совпадает с Queue.First()) Но мне интересно, означает ли это, что перечислитель будет буквально перечислять весь очередь до достижения последнего элемента. Поскольку мои очереди будут очень большими, это может быть проблемой.

РЕДАКТИРОВАТЬ:

Чтобы понять, что я пытаюсь сделать: скажем, я хочу вести ежеминутную базу данных о цене акций за последние 20 лет. Это будет много точек данных. Чтобы сделать это, я бы хотел ставить последнюю цену в очередь и ставить самую раннюю цену в очередь, когда размер очереди превышает 20 лет. Тем не менее, я также хочу удобный способ получить самую последнюю цену из очереди. Я знаю о Queue.Last(), который сделает свое дело, но я просто хочу знать, будет ли он ужасно неэффективным.

3 ответа

Решение

Если коллекция реализует IList<T> , то свойство indexer используется в обоих First() а также Last() (обычно это O(1), хотя это не обязательно).

В противном случае вызов First() будет принимать только первый элемент (и немедленно завершать работу, если перечислитель поддерживает отложенное выполнение), но вызов Last() Придется перечислять всю коллекцию.

IQueue<T> не реализует IList<T>,

Похоже, вы не хотите использовать очередь, но deque.

Делать Last вызов создаст Enumerator Например, частный внутренний класс для Queue<T> что будет использоваться для перечисления начала до конца, потому что Queue<T> не реализует IList<T> интерфейс. таким образом Last будет операция O(N).

Вы правы - для очередей Last будет повторяться по каждому элементу. Enumerable.Last имеет ярлык для ILists, но не для очередей.

Похоже, вы просто хотите очередь, которая помнит последний добавленный элемент. Вы можете просто создать простую обертку вокруг очереди, которая может эффективно вернуть последний элемент...

public class StockQueue<T>
{
    private readonly queue; 

    public StockQueue(Queue<T> source)
    {
        this.queue = source;
    }

    public T LastAdded {get; private set;}

    public Enqueue(T item)
    {
        // Remember the last item added
        this.lastAdded = item;
        this.queue.Enqueue(item);
    }

    // Implement any other Queue members you need, passing the calls through
    // to the internal queue.
    public T Dequeue()
    {
        return this.queue.Dequeue();
    }

    public T Peek()
    {
        return this.queue.Peek();
    }
}
Другие вопросы по тегам