Limit velikost fronty <T> v .NET?

hlasů
50

Mám fronty <T> objekt, který jsem se inicializuje s kapacitou 2, ale samozřejmě, že je jen kapacita a stále rozšiřuje, jak jsem přidávat položky. Je tam už objekt, který automaticky dequeues položky, když je dosažen limit, nebo je nejlepším řešením vytvořit svůj vlastní dědičnou třídu?

Položena 04/08/2008 v 15:47
zdroj uživatelem
V jiných jazycích...                            


7 odpovědí

hlasů
32

Já jsem vyrazil do základní verzi toho, co jsem hledal, že to není dokonalé, ale to bude dělat svou práci, dokud něco lepšího přijde.

public class LimitedQueue<T> : Queue<T>
{
    public int Limit { get; set; }

    public LimitedQueue(int limit) : base(limit)
    {
        Limit = limit;
    }

    public new void Enqueue(T item)
    {
        while (Count >= Limit)
        {
            Dequeue();
        }
        base.Enqueue(item);
    }
}
Odpovězeno 04/08/2008 v 15:57
zdroj uživatelem

hlasů
17

Doporučila bych, abyste vytáhnout C5 knihovny . Na rozdíl od SCG (System.Collections.Generic), C5 je naprogramován tak, aby rozhraní a navrženy tak, aby se dále dělit na podtřídy. Většina veřejných metody jsou virtuální a žádná ze tříd jsou uzavřeny. Tímto způsobem, nebudete muset používat tuto fuj „nové“ slovo, které by nemusely být důvodem, pokud vaše LimitedQueue<T>byli obsazeni do A SCG.Queue<T>. S C5 a použití v blízkosti stejný kód, jak si předtím, měli byste odvodit z CircularQueue<T>. CircularQueue<T>Vlastně implementuje stoh a fronty, takže se můžete dostat obě možnosti s limitem téměř zadarmo. Jsem přepsat jej dále s některými 3.5 konstrukty:

using C5;

public class LimitedQueue<T> : CircularQueue<T>
{
    public int Limit { get; set; }

    public LimitedQueue(int limit) : base(limit)
    {
        this.Limit = limit;
    }

    public override void Push(T item)
    {
        CheckLimit(false);
        base.Push(item);
    }

    public override void Enqueue(T item)
    {
        CheckLimit(true);
        base.Enqueue(item);
    }

    protected virtual void CheckLimit(bool enqueue)
    {
        while (this.Count >= this.Limit)
        {
            if (enqueue)
            {
                this.Dequeue();
            }
            else
            {
                this.Pop();
            }
        }
    }
}

Myslím si, že tento kód by měl dělat přesně to, co jste hledali.

Odpovězeno 24/10/2008 v 14:51
zdroj uživatelem

hlasů
5

Ty by měly vytvořit vlastní třídu, je ringbuffer by pravděpodobně vyhovovat vašim potřebám.

Datové struktury v NET, která umožňuje určit schopnost, s výjimkou pole, používá toto vybudovat vnitřní datové struktury používané pro uložení interních dat.

Například, pro seznam, kapacita se používá k velikosti vnitřní pole. Když začnete přidávat prvky do seznamu, bude to začít vyplnění tohoto pole z indexu 0 a nahoru, a když dosáhne své možnosti, zvyšuje kapacitu na novou vyšší kapacitou, i nadále plnit to nahoru.

Odpovězeno 04/08/2008 v 15:56
zdroj uživatelem

hlasů
3

No já doufám, že tato třída bude vám pomůže:
Vnitřně oběžník FIFO Buffer použít fronty <T> podle zadané velikosti. Jakmile se dosáhne velikost vyrovnávací paměti, bude to nahradí starší položky za nové.

Poznámka: Nemůžete odstranit položky v náhodném pořadí. Jsem na metodu Odebrat (T položka) pro návrat falešný. Pokud chcete, můžete upravit, aby neobsahovaly předměty náhodně

public class CircularFIFO<T> : ICollection<T> , IDisposable
{
    public Queue<T> CircularBuffer;

    /// <summary>
    /// The default initial capacity.
    /// </summary>
    private int capacity = 32;

    /// <summary>
    /// Gets the actual capacity of the FIFO.
    /// </summary>
    public int Capacity
    {
        get { return capacity; }          
    }

    /// <summary>
    ///  Initialize a new instance of FIFO class that is empty and has the default initial capacity.
    /// </summary>
    public CircularFIFO()
    {            
        CircularBuffer = new Queue<T>();
    }

    /// <summary>
    /// Initialize a new instance of FIFO class that is empty and has the specified initial capacity.
    /// </summary>
    /// <param name="size"> Initial capacity of the FIFO. </param>
    public CircularFIFO(int size)
    {
        capacity = size;
        CircularBuffer = new Queue<T>(capacity);
    }

    /// <summary>
    /// Adds an item to the end of the FIFO.
    /// </summary>
    /// <param name="item"> The item to add to the end of the FIFO. </param>
    public void Add(T item)
    {
        if (this.Count >= this.Capacity)
            Remove();

        CircularBuffer.Enqueue(item);
    }

    /// <summary>
    /// Adds array of items to the end of the FIFO.
    /// </summary>
    /// <param name="item"> The array of items to add to the end of the FIFO. </param>
     public void Add(T[] item)
    { 
        int enqueuedSize = 0;
        int remainEnqueueSize = this.Capacity - this.Count;

        for (; (enqueuedSize < item.Length && enqueuedSize < remainEnqueueSize); enqueuedSize++)
            CircularBuffer.Enqueue(item[enqueuedSize]);

        if ((item.Length - enqueuedSize) != 0)
        {
            Remove((item.Length - enqueuedSize));//remaining item size

            for (; enqueuedSize < item.Length; enqueuedSize++)
                CircularBuffer.Enqueue(item[enqueuedSize]);
        }           
    }

    /// <summary>
    /// Removes and Returns an item from the FIFO.
    /// </summary>
    /// <returns> Item removed. </returns>
    public T Remove()
    {
        T removedItem = CircularBuffer.Peek();
        CircularBuffer.Dequeue();

        return removedItem;
    }

    /// <summary>
    /// Removes and Returns the array of items form the FIFO.
    /// </summary>
    /// <param name="size"> The size of item to be removed from the FIFO. </param>
    /// <returns> Removed array of items </returns>
    public T[] Remove(int size)
    {
        if (size > CircularBuffer.Count)
            size = CircularBuffer.Count;

        T[] removedItems = new T[size];

        for (int i = 0; i < size; i++)
        {
            removedItems[i] = CircularBuffer.Peek();
            CircularBuffer.Dequeue();
        }

        return removedItems;
    }

    /// <summary>
    /// Returns the item at the beginning of the FIFO with out removing it.
    /// </summary>
    /// <returns> Item Peeked. </returns>
    public T Peek()
    {
        return CircularBuffer.Peek();
    }

    /// <summary>
    /// Returns the array of item at the beginning of the FIFO with out removing it.
    /// </summary>
    /// <param name="size"> The size of the array items. </param>
    /// <returns> Array of peeked items. </returns>
    public T[] Peek(int size)
    {
        T[] arrayItems = new T[CircularBuffer.Count];
        CircularBuffer.CopyTo(arrayItems, 0);

        if (size > CircularBuffer.Count)
            size = CircularBuffer.Count;

        T[] peekedItems = new T[size];

        Array.Copy(arrayItems, 0, peekedItems, 0, size);

        return peekedItems;
    }

    /// <summary>
    /// Gets the actual number of items presented in the FIFO.
    /// </summary>
    public int Count
    {
        get
        {
            return CircularBuffer.Count;
        }
    }

    /// <summary>
    /// Removes all the contents of the FIFO.
    /// </summary>
    public void Clear()
    {
        CircularBuffer.Clear();
    }

    /// <summary>
    /// Resets and Initialize the instance of FIFO class that is empty and has the default initial capacity.
    /// </summary>
    public void Reset()
    {
        Dispose();
        CircularBuffer = new Queue<T>(capacity);
    }

    #region ICollection<T> Members

    /// <summary>
    /// Determines whether an element is in the FIFO.
    /// </summary>
    /// <param name="item"> The item to locate in the FIFO. </param>
    /// <returns></returns>
    public bool Contains(T item)
    {
        return CircularBuffer.Contains(item);
    }

    /// <summary>
    /// Copies the FIFO elements to an existing one-dimensional array. 
    /// </summary>
    /// <param name="array"> The one-dimensional array that have at list a size of the FIFO </param>
    /// <param name="arrayIndex"></param>
    public void CopyTo(T[] array, int arrayIndex)
    {
        if (array.Length >= CircularBuffer.Count)
            CircularBuffer.CopyTo(array, 0);           
    }

    public bool IsReadOnly
    {
        get { return false; }
    }

    public bool Remove(T item)
    {
        return false; 
    }

    #endregion

    #region IEnumerable<T> Members

    public IEnumerator<T> GetEnumerator()
    {
       return CircularBuffer.GetEnumerator();
    }

    #endregion

    #region IEnumerable Members

    IEnumerator IEnumerable.GetEnumerator()
    {
        return CircularBuffer.GetEnumerator();
    }

    #endregion

    #region IDisposable Members

    /// <summary>
    /// Releases all the resource used by the FIFO.
    /// </summary>
    public void Dispose()
    {          
        CircularBuffer.Clear();
        CircularBuffer = null;
        GC.Collect();
    }

    #endregion
}
Odpovězeno 15/11/2011 v 13:40
zdroj uživatelem

hlasů
3

Proč by ne jen použít pole o velikosti 2? Fronta má být schopen dynamicky zvětšit a zmenšit.

Nebo vytvořit třídu obálky kolem instanci Queue<T>instance a pokaždé jeden enqueues <T>objektů, zkontrolujte velikost fronty. -Li větší než 2, dequeue první položku.

Odpovězeno 04/08/2008 v 15:52
zdroj uživatelem

hlasů
1

Pokud je to k ničemu nikoho, udělal jsem LimitedStack<T>.

public class LimitedStack<T>
{
    public readonly int Limit;
    private readonly List<T> _stack;

    public LimitedStack(int limit = 32)
    {
        Limit = limit;
        _stack = new List<T>(limit);
    }

    public void Push(T item)
    {
        if (_stack.Count == Limit) _stack.RemoveAt(0);
        _stack.Add(item);
    }

    public T Peek()
    {
        return _stack[_stack.Count - 1];
    }

    public void Pop()
    {
        _stack.RemoveAt(_stack.Count - 1);
    }

    public int Count
    {
        get { return _stack.Count; }
    }
}

To odstraní nejstarší položky (dno zásobníku), když se dostane příliš velké.

(Tato otázka byla první výsledek Google za „C # limit velikosti zásobníku“)

Odpovězeno 15/01/2012 v 06:28
zdroj uživatelem

hlasů
0

Souběžný Solution

public class LimitedConcurrentQueue<ELEMENT> : ConcurrentQueue<ELEMENT>
{
    public readonly int Limit;

    public LimitedConcurrentQueue(int limit)
    {
        Limit = limit;
    }

    public new void Enqueue(ELEMENT element)
    {
        base.Enqueue(element);
        if (Count > Limit)
        {
            TryDequeue(out ELEMENT discard);
        }
    }
}

Poznámka: Vzhledem k tomu, Enqueueovládací prvky přidání prvků, a činí tak jeden po druhém, není třeba vykonat whilepro TryDequeue.

Odpovězeno 09/05/2018 v 20:39
zdroj uživatelem

Cookies help us deliver our services. By using our services, you agree to our use of cookies. Learn more