2009-08-20 12 views
7

Supponiamo di avere una raccolta a rotazione di valori in cui viene specificata la dimensione della raccolta e ogni volta che viene aggiunto un nuovo valore, vengono eliminati tutti i vecchi valori oltre la dimensione specificata. Ovviamente (e ho provato questo) il miglior tipo di raccolta da utilizzare per questo comportamento è una coda:Come otterresti il ​​primo e l'ultimo elemento in una coda?

myQueue.Enqueue(newValue) 
If myQueue.Count > specifiedSize Then myQueue.Dequeue() 

Tuttavia, quello che se voglio calcolare la differenza tra il primo e l'ultimo elemento nella coda? Ovviamente non posso accedere agli articoli per indice. Ma passare da una coda a qualcosa che implementa IList sembra eccessivo, così come scrivere una nuova classe in stile Queue. In questo momento ho:

Dim firstValue As Integer = myQueue.Peek() 
Dim lastValue As Integer = myQueue.ToArray()(myQueue.Count - 1) 
Dim diff As Integer = lastValue - firstValue 

che richiamano alla ToArray() mi preoccupa, ma un'alternativa superiore non è venuta a me. Eventuali suggerimenti?

+0

C# non ha un tipo di coda di riacquisto? –

+0

No, C# non ha alcun tipo, .Net è ciò che ha tipi; e .Net non ha un tipo di Dequeue, ha un tipo Queue/Queue che ha un metodo Dequeue. –

risposta

14

Una cosa che si potrebbe fare è avere una variabile temporanea che memorizza il valore che è stato appena accodato perché quello sarà l'ultimo valore e quindi è possibile accedere alla variabile per ottenere quel valore.

+0

All'incirca nello stesso periodo in cui hai fornito questa risposta mi sono reso conto di quanto semplice fosse la soluzione (ciò che hai suggerito, in sostanza). Buona chiamata! –

+0

Grazie. Sono felice di poter dare un buon suggerimento. – murgatroid99

2

La soluzione migliore è quella di tenere traccia dell'ultimo valore aggiunto a Queue, quindi utilizzare la funzione myQueue.Peek() per visualizzare la voce "prima" (che significa successivo) nell'elenco senza rimuoverla.

1

È potrebbe usare una deque (d ouble- e nded coda).

Non penso ce ne sia uno integrato in System.Collections (.Generic) ma ecco alcune informazioni sulla struttura dati. Se hai implementato qualcosa di simile, potresti semplicemente utilizzare PeekLeft() e PeekRight() per ottenere il primo e l'ultimo valore.

Ovviamente, spetterà a te decidere se implementare o meno la propria deque è preferibile trattare con l'asperità di ToArray(). :)

http://www.codeproject.com/KB/recipes/deque.aspx

10

sembra se avete bisogno di un rapido accesso alla prima voce della lista, allora si sta utilizzando la struttura dati sbagliato. Passa invece a LinkedList, che ha convenientemente le proprietà First e Last.

Assicurarsi di aggiungere e rimuovere elementi all'elenco collegato utilizzando AddLast e RemoveFirst per mantenere la proprietà Queue. Per evitare di violare inavvertitamente la proprietà Queue, prendere in considerazione la creazione di una classe wrapper attorno all'elenco collegato e l'esposizione delle sole proprietà necessarie dalla coda.

+0

Sfortunato ma meglio che tenere traccia dell'ultimo aggiunto al di fuori della struttura dati stessa. –

4
public class LastQ<T> : Queue<T> 
{ 
    public T Last { get; private set; } 

    public new void Enqueue(T item) 
    { 
     Last = item; 
     base.Enqueue(item); 
    } 
} 

Edit: Ovviamente questa classe di base dovrebbe essere più robusto per fare le cose come proteggere le ultime proprietà su una coda vuota. Ma questo dovrebbe essere sufficiente per l'idea di base.

+0

Ha! Questo è quasi VERBATIM il codice che ho appena scritto.(L'unica differenza è il nome della classe e ho inserito Last = item dopo base.Enqueue (item)). –

+0

Cosa succede quando l'ultimo elemento viene rimosso? Come imposteresti 'Last' al penultimo elemento? – nawfal

Problemi correlati