Reputation: 21194
What's the most performant way to remove n elements from a collection and add those removed n elements to an already existing, different, collection?
Currently I've got this:
var entries = collection.Take(5).ToList();
foreach(var entry in entries)
collection.Remove(entry);
otherCollection.AddRange(entries);
However, this doesn't look performant at all to me (multiple linear algorithms instead of only one).
A possible solution may of course change the collection implementation - as long as the following requirements are met:
otherCollection
must implement IEnumerable<T>
, it is currently of type List<T>
collection
must implement ICollection<T>
, it is currently of type LinkedList<T>
Hint: entries do not necessarily implement Equals()
or GetHashCode()
.
What's the most performant way to reach my goal?
As it has been obviously too hard to understand my performance considerations, here once more my code example:
var entries = collection.Take(1000).ToList(); // 1000 steps
foreach(var entry in entries) // 1000 * 1 steps (as Remove finds the element always immediately at the beginning)
collection.Remove(entry);
otherCollection.AddRange(entries); // another 1000 steps
= 3000 steps in total => I want to reduce it to a single 1000 steps.
Upvotes: 4
Views: 7191
Reputation: 3117
With your use case the best data structure seems to be a queue. When using a queue your method can look this this:
public static IEnumerable<T> TakeAndRemove<T>(Queue<T> queue, int count)
{
count = Math.Min(queue.Count, count);
for (int i = 0; i < count; i++)
yield return queue.Dequeue();
}
Upvotes: 2
Reputation: 31
The previous function only returns half results. You should use:
public static IEnumerable<T> TakeAndRemove<T>(Queue<T> queue, int count)
{
for (int i = 0; i < count && queue.Count > 0; i++)
yield return queue.Dequeue();
}
Upvotes: 3