Tutorial :How to remove a stack item which is not on the top of the stack in C#



Question:

Unfortunately an item can only be removed from the stack by "pop". The stack has no "remove" method or something similar, but I have a stack (yes I need a stack!) from which I need to remove some elements between.

Is there a trick to do this?


Solution:1

If you need to remove items that aren't on the top, then you need something other than a stack.

Try making your own implementation of a stack from a List. Then you get to implement your own push and pop functions (add & remove on the list), and your own special PopFromTheMiddle function.

For example

public class ItsAlmostAStack<T>  {      private List<T> items = new List<T>();        public void Push(T item)      {          items.Add(item);      }      public T Pop()      {          if (items.Count > 0)          {              T temp = items[items.Count - 1];              items.RemoveAt(items.Count - 1);              return temp;          }          else              return default(T);      }      public void Remove(int itemAtPosition)      {          items.RemoveAt(itemAtPosition);      }  }  


Solution:2

Consider using different container. Maybe a LinkedList. Then you can use

AddFirst  AddLast  RemoveLast  RemoveFirst

just like pop/push from stack and you can use

Remove

to remove any node from the middle of the list


Solution:3

Perhaps an extension method would work, although, I suspect that a different data structure entirely is really needed.

public static T Remove<T>( this Stack<T> stack, T element )  {       T obj = stack.Pop();       if (obj.Equals(element))       {           return obj;       }       else       {          T toReturn = stack.Remove( element );          stack.Push(obj);          return toReturn;       }  }  


Solution:4

In a true stack, this can only be done one way -

Pop all of the items until you remove the one you want, then push them back onto the stack in the appropriate order.

This is not very efficient, though.

If you truly want to remove from any location, I'd recommend building a pseudo-stack from a List, LinkedList or some other collection. This would give you the control to do this easily.


Solution:5

You could use a LinkedList

List based removal will likely be less efficient. In removal by reference List based stacks will have O(N) search and O(N) resizing. LinkedList search is O(N) and removal is O(1). For removal by index, LinkedList should have O(N) traversal and O(1) removal, while List will have O(1) traversal (because it is indexing) and O(N) removal due to resizing.

Besides efficiency, a LinkedList implementation will keep you in the standard library, opening your code to more flexibility and have you writing less.

This should be able to handle Pop, Push, and Remove

    public class FIFOStack<T> : LinkedList<T>      {          public T Pop()          {              T first = First();              RemoveFirst();              return first;          }            public void Push(T object)          {              AddFirst(object);          }            //Remove(T object) implemented in LinkedList     }  


Solution:6

Then it is not a stack right? Stack is LAST in FIRST out. You will have to write a custom one or choose something else.


Solution:7

   Stack temp = new Stack();     object x, y;     While ((x = myStack.Pop()) != ObjectImSearchingFor)         temp.Push(x);     object found = x;     While ((y = temp.Pop()) != null)        myStack.Push(y);  


Solution:8

The constructor of a Stack<> takes IEnumerable<> as a parameter. So it would be possible to perform the following:

myStack = new Stack<item>( myStack.Where(i => i != objectToRemove).Reverse() );  

This is non performant in a number of ways.


Solution:9

A trick I use in hairy situations is adding a 'deprecated' flag to the items in the stack. When I want to 'remove' an item, I simply raise that flag (and clean up any resources that are taken by the object). Then when Pop()ing items I simply check if the flag is raised, and pop again in a loop until a non-deprecated item is found.

do   {       obj = mQueue.Pop();    } while (obj.deprecated);    

You can manage your own item-count to know how many 'real' items are still in the queue, and obviously locking should be employed if this is required for multi-threaded solution.

I found that for queues that have constant flow through them - items pushed and popped - it's much more efficient to hanle it this way, its the fastest you can get (paying O(1) for removing an item from the middle) and memory wise if the object that is retained is small, it's mostly irrelevant if the items flow in a reasonable pace.


Solution:10

hmmmm...... I agree with the previous two answers but if you are looking to hack your way just pop and save all elements until you get to the one you want, and the re-push them all

Yes is ugly, badly performing, probably weird code that will need a long comment explaining why, but you could do it....


Solution:11

I came across this question. In my code I created my own extension method:

public static class StackExtensions  {      public static void Remove<T>(this Stack<T> myStack, ICollection<T> elementsToRemove)      {          var reversedStack = new Stack<T>();            while(myStack.Count > 0)          {              var topItem = myStack.Pop();              if (!elementsToRemove.Contains(topItem))              {                  reversedStack.Push(topItem);              }          }            while(reversedStack.Count > 0)          {              myStack.Push(reversedStack.Pop());          }                 }  }  

And I call my method like this:

var removedReportNumbers =   selectedReportNumbersInSession.Except(selectedReportNumbersList).ToList();    selectedReportNumbersInSession.Remove(removedReportNumbers);  

Note:If u also have question or solution just comment us below or mail us on toontricks1994@gmail.com
Previous
Next Post »