-2
// Program (Main)
var s = new UniqueStack<int>();
            s.Push(3);
            s.Push(2);
            s.Push(1);
            s.Push(1);                    // Exception
            while (s.Count > 0)
            {
                Console.WriteLine(s.Pop());     // 1->2->3
            }

I want to bring this Code to life. I had a very similiar task once and tried to make it for this task works, but it didn't works well, because I have some parts of it as blanks, because i dont know how to go forward.

// UniqueStack (Class)
using System;
using System.Collections;

namespace StackTest
{
    internal class UniqueStack<T> : ICollection
    {

        private ArrayList<T> items = new ArrayList<T>();

        public int Count
        {
            get { return items.Count; }
        }
        public UniqueStack()
        {
        }

        public void Push(T item)
        {
            items.Add(item);

        }

        public T Pop()
        {
            T item;

            if (items.Count == 0)
                throw new InvalidOperationException("No items in stack");

            item = items[items.Count - 1];
            items.RemoveAt(items.Count - 1);

            return item;
        }
    }



}

I clearly see, that this Code didn't throw an exception, when its a clone of a existing pushed number. And my ICollection don't work for this example, because the code doesn't work with it. Any one who can help an very poor skilled programer?

Thank you!

internal class UniqueStack<T>
    {

        private List<T> items = new List<T>();

        public int Count
        {
            get { return items.Count; }
        }
        public UniqueStack()
        {
        }

        public void Push(T item)
        {
            if (items.Contains(item))
            {
            throw new System.InvalidOperationException("Doppelte Werte sind nicht erlaubt!");

            }
            items.Add(item);
        }

        public T Pop()
        {
            T item;

            if (items.Count == 0)
                throw new InvalidOperationException("No items in stack");

            item = items[items.Count - 1];
            items.RemoveAt(items.Count - 1);

            return item;
        }


        public override string ToString()
        {
            string s = "";



            while (items != null)
            {
                s += items.ToString() + " -> ";

            }
            s += "Count: " + Count.ToString();

            return s;
        }
    }

My code does work, but I can't display it right. It says 1 2 3

Instead of 1 - > 2 - > 3

pppery
  • 3,731
  • 22
  • 33
  • 46
Unlexs
  • 29
  • 5

1 Answers1

1

If you want a Stack that does not allow duplicates then you can use a Stack<T> as the underlying type and a HashSet<T> to determine if the items you push already exist in the stack. You can even include a constructor that take a IEqualityComparer<T> so that you can tell it how to determine if two items are equal.

public class UniqueStack<T> : IEnumerable<T>, IReadOnlyCollection<T>
{
    private readonly Stack<T> _stack = new Stack<T>();
    private readonly HashSet<T> _hash;

    public UniqueStack()
    {
        _hash = new HashSet<T>();
    }

    public UniqueStack(IEqualityComparer<T> comparer)
    {
        _hash = new HashSet<T>(comparer);
    }

    public void Clear()
    {
        _stack.Clear();
        _hash.Clear();
    }

    public T Peek() => _stack.Peek();

    public T Pop()
    {
        var item = _stack.Pop();
        _hash.Remove(item);
        return item;
    }

    public void Push(T item)
    {
        // HashSet.Add returns true if the item was not already in the set.
        if (_hash.Add(item))
        {
            _stack.Push(item);
        }
        else
        {
            // You can throw an exception on duplicate or ignore them.
        }
    }

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

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

    public int Count => _stack.Count;

    // Here's a ToString override that does what you want
    public override string ToString() =>
        string.Join(" -> ", _stack);
}
juharr
  • 31,741
  • 4
  • 58
  • 93
  • Thank you, juharr. I know, that there is Stack from Microsoft itself, but I try to understand how it works. My last problem is just to print the items with -> between and side by side. – Unlexs Jun 16 '20 at 13:50
  • I've added a `ToString` override. Note that if the stack is empty then it returns an empty string. – juharr Jun 16 '20 at 13:52
  • With my code your toString gives just out, what i've got before. 1 2 3 and not 1 -> 2-> 3 – Unlexs Jun 16 '20 at 14:02
  • I don't get, why my question is closed. @servy – Unlexs Jun 16 '20 at 16:45