2010-12-04 5 views
2

Ich habe eine Reihe von IDs, auf die ich einige Operationen ausführen:Gibt es etwas wie eine erweiterbare Warteschlange in C#?

Queue<string> queue = new Queue<string>(); 
queue.Enqueue("1"); 
queue.Enqueue("2"); 
... 
queue.Enqueue("10"); 

foreach (string id in queue) 
{ 
    DoSomeWork(id); 
} 

static void DoSomeWork(string id) 
{ 
    // Do some work and oooo there are new ids which should also be processed :) 
    foreach(string newID in newIDs) 
    { 
     if(!queue.Contains(newID)) queue.Enqueue(newID); 
    } 
} 

Ist es möglich, einige neue Elemente zu queue in DoSomeWork() hinzuzufügen, die auch bei der Haupt foreach-Schleife verarbeitet werden?

Antwort

1

Verwenden Dequeue anstelle einer foreach-Schleife. Die meisten Enumeratoren werden ungültig, wenn der zugrunde liegende Container geändert wird. Und En-/Dequeue sind die natürlichen Operationen in einer Warteschlange. Sonst könnten Sie List<T> oder HashSet<T>

while(queue.Count>0) 
{ 
    var value=queue.Dequeue(); 
    ... 
} 

Um zu überprüfen, verwenden, wenn ein Element bereits ein HashSet<T> ist eine schnelle Lösung verarbeitet wurde. In diesen Fällen verwende ich normalerweise eine Kombination aus HashSet und Queue. Der Vorteil dieser Lösung ist, dass es O (n) ist, weil das Überprüfen und Hinzufügen zu einem HashSet O (1) ist. Ihr ursprünglicher Code war O (n^2), da Contains auf einem Queue O (n) ist.

Queue<string> queue=new Queue<string>(); 
HashSet<string> allItems=new HashSet<string>(); 

void Add(string item) 
{ 
    if(allItems.Add(item)) 
    queue.Enqueue(item); 
} 

void DoWork() 
{ 
    while(queue.Count>0) 
    { 
     var value=queue.Dequeue(); 
     ... 
    } 
} 
+0

Wie wird diese Arbeit mit einem HashSet ? – Makara

+0

@Makara Ein Beispiel hinzugefügt, in dem ich eine Warteschlange verwende, um die unverarbeiteten Elemente zu speichern, und ein HashSet, um Duplikate zu vermeiden. – CodesInChaos

0

Es ist üblich, dass Schleifeniterationen mehr Arbeit hinzufügen; Übergeben Sie einfach die Warteschlange in die Methode als Argument, und das Hinzufügen sollte in Ordnung sein.

Das Problem ist, dass ou sollte Dequeue werden:

while(queue.Count>0) { 
    DoSomeWork(queue.Dequeue()); 
} 
3

Was Sie tun, ist einen Iterator über eine sich ändernde Sammlung zu verwenden. Dies ist eine schlechte Vorgehensweise, da einige Auflistungen eine Ausnahme auslösen (z. B. sollte sich die Auflistung während der Aufzählung nicht ändern).

Verwenden Sie die folgende Vorgehensweise, die auch neue Objekte zu verwenden ist:

while (queue.Count > 0) 
{ 
    DoSomeWork(queue.Dequeue()); 
} 
+0

Ist das auch mit einem HashSet möglich? – Makara

+0

Nein, aber mit einer 'List <>', wenn Sie den Listenindex verwenden. Natürlich können Sie auch einen 'HashSet <>' und eine 'Queue <>' haben, um zu wissen, welche Artikel bereits bearbeitet wurden (mit dem Set) und welche Artikel verarbeitet werden müssen (Queue). – Lucero

Verwandte Themen