Stack implementation in Swift
Solution 1
Details
- Swift 5.1, Xcode 11.3.1
Generic Stack Implementation
Stackable protocol
protocol Stackable {
associatedtype Element
func peek() -> Element?
mutating func push(_ element: Element)
@discardableResult mutating func pop() -> Element?
}
extension Stackable {
var isEmpty: Bool { peek() == nil }
}
Stack
struct Stack<Element>: Stackable where Element: Equatable {
private var storage = [Element]()
func peek() -> Element? { storage.last }
mutating func push(_ element: Element) { storage.append(element) }
mutating func pop() -> Element? { storage.popLast() }
}
extension Stack: Equatable {
static func == (lhs: Stack<Element>, rhs: Stack<Element>) -> Bool { lhs.storage == rhs.storage }
}
extension Stack: CustomStringConvertible {
var description: String { "\(storage)" }
}
extension Stack: ExpressibleByArrayLiteral {
init(arrayLiteral elements: Self.Element...) { storage = elements }
}
Usage
var stack = Stack<Int>()
stack.push(1)
stack.push(2)
stack.push(3)
print(stack.peek())
print(stack.pop())
print(stack)
print(stack == Stack<Int>())
stack = [3,2,1]
print(stack)
Solution 2
There's no problem with what you're doing there - that's just not the syntax for declaring an array. If you want an array of 5 stacks, you can do this:
[IntStack(), IntStack(), IntStack(), IntStack(), IntStack()]
Or, you can initialise the array like this:
Array(count: 5, repeatedValue: IntStack())
Also, you don't need to mark your functions as mutating
unless they actually mutate the structure - so count()
and show()
don't need it.
Solution 3
It's possible to just extend arrays with stack specific methods. This might or might not be what you want, depending on if you want to disallow array like access.
protocol Stack {
associatedtype Element
mutating func push(item: Element)
// allows discarding the result without generating a warning.
@discardableResult
mutating func pop() -> Element?
func peek() -> Element?
var count: Int { get }
}
extension Array: Stack {
mutating func push(item: Element) {
self.append(item)
}
mutating func pop() -> Element? {
if let last = self.last {
self.remove(at: self.count - 1)
return last
}
return .none
}
func peek() -> Element? {
self.last
}
}
Simple test case:
class StackTests: XCTestCase {
func testExample() throws {
var stack = Array<Int>()
XCTAssertEqual(stack.peek(), .none, "stack is empty, peek returns none")
XCTAssertEqual(stack.pop(), .none, "stack is empty, pop returns none")
stack.push(item: 0)
stack.push(item: 1)
stack.push(item: 2)
XCTAssertEqual(stack.peek(), 2)
XCTAssertEqual(stack.pop(), 2)
XCTAssertEqual(stack.peek(), 1)
XCTAssertEqual(stack.pop(), 1)
XCTAssertEqual(stack.peek(), 0)
XCTAssertEqual(stack.pop(), 0)
}
}
Solution 4
There is no need to declare the size of the stack when you init it. Jus calling this should be enough.
var lines = IntStack()
Also note that your count() and show() methods should not be mutating since they don't modify the struct in any way.
Related videos on Youtube
Plinio Vilela
Updated on October 18, 2022Comments
-
Plinio Vilela over 1 year
I'm new to Swift and iOS programming.
I'm trying to test out a simple algorithm and need an array of Stacks. Don't have to be anything fancy (Stacks of Ints will do).
I got the Stack implementation from The Swift Programming Language documentation:
struct IntStack { var items = [Int]() mutating func push(item: Int) { items.append(item) } mutating func pop() -> Int { return items.removeLast() } mutating func count() -> Int { return items.count } mutating func show() { println(items) } }
The count and show functions are my contribution. But when I try to declare an array of Stacks I get an error...
var lines = IntStack()[5]
"IntStack" does not have a member named subscript
I'm guessing it has something to do with Optionals but can figure out what it is.
Any help?
-
Martin R almost 9 yearsI don't think that you need
Repeat
here,Array(count: 5, repeatedValue: IntStack())
should work as well. -
oisdk almost 9 yearsOoh, didn't know about that. Thanks!
-
Plinio Vilela almost 9 yearsThanks guys! I used: Array(count: 5, repeatedValue: IntStack()) and removed the mutating from count() and show() (never use CMD+C CMD+V while programming), and it worked! This Array instantiation syntax is very weird to me, but I guess I got the point. Thanks again!!
-
Caleb almost 5 yearsOP is trying to declare an array of stacks, not a single stack with a particular size.
-
Binarian almost 5 yearsAnd you are not showing any Stack implementation at all.
-
Kaolin Fire over 3 years@PlinioVilela this is ancient but seems like this should be the accepted answer?