Is there a built in stack implementation in Swift? - swift

I want to use Stack in my swift code. I couldn't find any inbuilt stack implementation in Swift like java.util.Stack in Java.
I could implement my own Stack in swift but I would prefer a built-in one.

No, but you could implement your own pretty easily
struct Stack {
private var array: [Any] = []
mutating func push(_ element: Any) {
array.append(element)
}
mutating func pop() -> Any? {
return array.popLast()
}
func peek() -> Any? {
guard let top = array.last else { return nil }
return top
}
}

There is an implementation in the documentation at:
https://docs.swift.org/swift-book/LanguageGuide/Generics.html
that is also type agnostic.
struct Stack<Element> {
var items = [Element]()
mutating func push(_ item: Element) {
items.append(item)
}
mutating func pop() -> Element {
return items.removeLast()
}
}

Finally, Apple has released Swift Swift Collections. The Collections package has an implementation of Deque. I can use this as a Stack.

Learned GenericStack with Swift 5.7.1 with Xcode 14:
1. First make a Protocol Stackable :
protocol Stackable {
associatedtype ObjectType
func push(value:ObjectType)
func pop()
func peek()->ObjectType?
}
2. Make a GenericStack class using Stackable :
class GenericStack<T>:Stackable {
private var list:[T] = [T]()
public var elements:[T]{
return list
}
func push(value: T) {
list.append(value)
}
func pop() {
if !list.isEmpty {
list.removeLast()
}
}
func peek() -> T? {
return list.last
}
typealias ObjectType = T
}
3. Use it with any Data Type:
var stackInt:GenericStack<Int> = GenericStack<Int>()
print(stackInt.push(value: 5))
print(stackInt.push(value: 7))
print(stackInt.elements)
var stackChar:GenericStack<Character> = GenericStack<Character>()
print(stackChar.push(value: "A"))
print(stackChar.push(value: "B"))
print(stackChar.elements)
var stackString:GenericStack<String> = GenericStack<String>()
print(stackString.push(value: "Abhi"))
print(stackString.push(value: "test"))
print(stackString.elements)
Video of execution and learning stack in swift : XcodePlaygroundWork

Related

Add object to an array that confirm to the protocol that has associated type in it

I have a problem to write the code that puts objects into the observers array. The objects that are problematic implement the Observer protocol.
Here is the code that shows what I want to do:
protocol Observer {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers = Array<Observer>()
mutating func attach(observer: Observer) {
observers.append(observer)
}
func notyfi(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}
If your deployment target is at least a late 2022 release (iOS 16, macOS 13, etc.), you can use a constrained existential:
protocol Observer<ValueType> {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers = Array<any Observer<T>>()
mutating func attach(observer: any Observer<T>) {
observers.append(observer)
}
func notify(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}
If your deployment target is earlier, the Swift runtime doesn't support constrained existentials. (From SE-0353: “It is worth noting that this feature requires revisions to the Swift runtime and ABI that are not backwards-compatible nor backwards-deployable to existing OS releases.”) But you can use closures instead:
protocol Observer<ValueType> {
associatedtype ValueType
func update(value: ValueType)
}
struct Subject<T> {
private var observers: [(T) -> Void] = []
mutating func attach<O: Observer>(observer: O)
where O.ValueType == T
{
observers.append { observer.update(value: $0) }
}
func notify(value: T) {
for observer in observers {
observer(value)
}
}
}
Why don't you use the Observer as the generic parameter?
struct Subject<O: Observer> {
typealias T = O.ValueType
private var observers = Array<O>()
mutating func attach(observer: O) {
observers.append(observer)
}
func notyfi(value: T) {
for observer in observers {
observer.update(value: value)
}
}
}

How To Tell How Many Elements Are In A Swift Stack

I am using Swift stacks for my calculator app that I am making. But I need to tell if there is only one element in my stack for my calculator app to function correctly. Does anybody know how to count the number of elements in a Swift stack?
struct Stack {
fileprivate var operators: [String] = []
mutating func push(_element: String) {
operators.append(_element)
}
mutating func pop() -> String? {
return operators.popLast()
}
func peek() -> String? {
return operators.last
}
}
Swift doesn't have a built-in Stack type.
To reveal the size of your custom Stack struct, add a size property to your Stack that returns the number of items in the operators array:
struct Stack {
fileprivate var operators: [String] = []
mutating func push(_ element: String) {
operators.append(element)
}
mutating func pop() -> String? {
return operators.popLast()
}
func peek() -> String? {
return operators.last
}
var size: Int { return operators.count }
}
Example
var stack = Stack()
stack.push("+")
print(stack.size) // 1
_ = stack.pop()
print(stack.size) // 0

Find an element in a stack data structure swift 4

If found this stack data structure at Ray Wenderlich and it works well:
public struct Stack<T> {
fileprivate var array = [T]()
public var isEmpty: Bool {
return array.isEmpty
}
public var count: Int {
return array.count
}
public mutating func push(_ element: T) {
array.append(element)
}
public mutating func pop() -> T? {
return array.popLast()
}
public var top: T? {
return array.last
}
}
I'd like to add another method for finding an element within the stack so that I don't try to add an element more than once. For example, I'm keeping a stack of ViewControllers.
var vcStack = Stack<UIViewController>()
vcStack.push(VC1)
vcStack.push(VC2)
I'd like to be able to query the Stack and get back a boolean if the input VC exists (or not), like this:
if vcStack.hasElement(VC1) {
//do something
}
This is pseudo-code - what would the Swift 4 code be?
public var hasElement(_ element: T): -> Bool {
if array.contains(element){
return true
}else{
return false
}
}
If you define your Stack class to require that its elements conform to Equatable:
public struct Stack<T> where T: Equatable {
then your hasElement would be:
public func hasElement(_ element: T) -> Bool {
return array.contains(element)
}
Or you can leave Stack declared as you have it, and add hasElement to an extension:
public extension Stack where T: Equatable {
public func hasElement(_ element: T) -> Bool {
return array.contains(element)
}
}
This allows you have to have a Stack of anything but the hasElement function will only be available if it's a Stack of Equatable values.
struct MenuData {
let title : String!
let imageName : String!
}
class MoreTV: UITableView {
var aryMenu : [MenuData] = [MenuData(title: "My Profile".localized, imageName: "ic-user"),]
}

Array of protocol type

I have checked all answers about this problem on stackoverflow, but still can not figure out how to fix this.
My model looks like this
protocol Commandable: Equatable {
var condition: Condition? {get set}
func execute() -> SKAction
}
And 3 structs which implement this protocol
struct MoveCommand: Commandable {
var movingVector: CGVector!
//MARK: - Commandable
var condition: Condition?
func execute() -> SKAction {
...
}
}
extension MoveCommand {
// MARK:- Equatable
static func ==(lhs: MoveCommand, rhs: MoveCommand) -> Bool {
return lhs.movingVector == rhs.movingVector && lhs.condition == rhs.condition
}
}
struct RotateCommand: Commandable {
var side: RotationSide!
// MARK: - Commandable
var condition: Condition?
func execute() -> SKAction {
...
}
}
extension RotateCommand {
// MARK: - Equatable
static func ==(lhs: RotateCommand, rhs: RotateCommand) -> Bool {
return lhs.side == rhs.side && lhs.condition == rhs.condition
}
}
The problems start when I am trying to create third structure which has array of [Commandable]:
struct FunctionCommand: Commandable {
var commands = [Commandable]()
The compiler output: Protocol 'Commandable' can only be used as a generic constraint because it has Self or associated type requirements. Then i rewrote my struct in this way:
struct FunctionCommand<T : Equatable>: Commandable {
var commands = [T]()
I resolve this problem but new problem has appeared. Now i can't create FunctionCommand with instances of Rotate and Move command, only with instances of one of them :( :
let f = FunctionCommand(commands: [MoveCommand(movingVector: .zero, condition: nil),
RotateCommand(side: .left, condition: nil)], condition: nil)
Any Help would be appreciated.
Update: That article helped me to figure out - https://krakendev.io/blog/generic-protocols-and-their-shortcomings
What you need to do is to use type erasure, much like AnyHashable does in the Swift Standard Library.
You can't do:
var a: [Hashable] = [5, "Yo"]
// error: protocol 'Hashable' can only be used as a generic constraint because it has Self or associated type requirements
What you have to do is to use the type-erased type AnyHashable:
var a: [AnyHashable] = [AnyHashable(5), AnyHashable("Yo")]
a[0].hashValue // => shows 5 in a playground
So your solution would be to first split the protocol in smaller parts and promote Equatable to Hashable (to reuse AnyHashable)
protocol Conditionable {
var condition: Condition? { get set }
}
protocol Executable {
func execute() -> SKAction
}
protocol Commandable: Hashable, Executable, Conditionable {}
Then create an AnyCommandable struct, like this:
struct AnyCommandable: Commandable, Equatable {
var exeBase: Executable
var condBase: Conditionable
var eqBase: AnyHashable
init<T: Commandable>(_ commandable: T) where T : Equatable {
self.condBase = commandable
self.exeBase = commandable
self.eqBase = AnyHashable(commandable)
}
var condition: Condition? {
get {
return condBase.condition
}
set {
condBase.condition = condition
}
}
var hashValue: Int {
return eqBase.hashValue
}
func execute() -> SKAction {
return exeBase.execute()
}
public static func ==(lhs: AnyCommandable, rhs: AnyCommandable) -> Bool {
return lhs.eqBase == rhs.eqBase
}
}
And then you can use it like this:
var a = FunctionCommand()
a.commands = [AnyCommandable(MoveCommand()), AnyCommandable(FunctionCommand())]
And you can easily access properties of commands, because AnyCommandable implements Commandable
a.commands[0].condition
You need to remember to now add Hashable and Equatable to all your commands.
I used those implementations for testing:
struct MoveCommand: Commandable {
var movingVector: CGVector!
var condition: Condition?
func execute() -> SKAction {
return SKAction()
}
var hashValue: Int {
return Int(movingVector.dx) * Int(movingVector.dy)
}
public static func ==(lhs: MoveCommand, rhs: MoveCommand) -> Bool {
return lhs.movingVector == rhs.movingVector
}
}
struct FunctionCommand: Commandable {
var commands = [AnyCommandable]()
var condition: Condition?
func execute() -> SKAction {
return SKAction.group(commands.map { $0.execute() })
}
var hashValue: Int {
return commands.count
}
public static func ==(lhs: FunctionCommand, rhs: FunctionCommand) -> Bool {
return lhs.commands == rhs.commands
}
}
I think it can be easily done by introduction of your own CustomEquatable protocol.
protocol Commandable: CustomEquatable {
var condition: String {get}
}
protocol CustomEquatable {
func isEqual(to: CustomEquatable) -> Bool
}
Then, you objects have to conform to this protocol and additionally it should conform Equitable as well.
struct MoveCommand: Commandable, Equatable {
let movingVector: CGRect
let condition: String
func isEqual(to: CustomEquatable) -> Bool {
guard let rhs = to as? MoveCommand else { return false }
return movingVector == rhs.movingVector && condition == rhs.condition
}
}
struct RotateCommand: Commandable, Equatable {
let side: CGFloat
let condition: String
func isEqual(to: CustomEquatable) -> Bool {
guard let rhs = to as? RotateCommand else { return false }
return side == rhs.side && condition == rhs.condition
}
}
All you need to do now is connect your CustomEquatable protocol to Swift Equatable through generic extension:
extension Equatable where Self: CustomEquatable {
static func ==(lhs: Self, rhs: Self) -> Bool {
return lhs.isEqual(to: rhs)
}
}
It's not a perfect solution, but now, you can store your objects in a array of protocol objects and use == operator with your objects as well. For example(I simplified objects a little bit):
let move = MoveCommand(movingVector: .zero, condition: "some")
let rotate = RotateCommand(side: 0, condition: "some")
var array = [Commandable]()
array.append(move)
array.append(rotate)
let equal = (move == MoveCommand(movingVector: .zero, condition: "some"))
let unequal = (move == MoveCommand(movingVector: .zero, condition: "other"))
let unequal = (move == rotate) // can't do this, compare different types
PS. Using var on struct is not a good practice, especially for performance reasons.
I believe the problem here is that the equatable protocol has self requirements. So you can solve you problem by removing equatable protocol from your Commandable protocol and make your your structs equatable instead. This will of course limit your protocol but maybe it is a trade-off that is reasonable?

Access to stored properties of a struct from a extension in Swift

I'm trying to implement a Stack struct in Swift and making it comply to Generator and Sequence.
class Stack<T> {
var items:Array<T>
var depth : Int{ return items.count}
init(){
items = Array<T>()
}
func push(elm:T){
items += elm
}
func pop()->T?{
if depth > 0{
return items.removeLast()
}else{
return nil
}
}
}
I get into trouble when trying to make it comply to Generator. I tried adding a nested type through an extension, that's when I get an error:
extension Stack{
struct StackGenerator: Generator{
var current = 0
mutating func next() -> T?{
let rc = items[current] // Get an error here: can't access items in Stack
}
}
}
The compiler won't let me access the Stack.items property form within StackGenerator. Is this to be expected? How can I work around this?
Generic types can't have nested types - you need to either build StackGenerator outside of your Stack declaration, or use the GeneratorOf<T> type in your generate function.
The first option could look like this:
class Stack<T> : SequenceType {
var items: Array<T>
var depth: Int { return items.count }
init(){
items = Array<T>()
}
func push(elm:T){
items += [elm]
}
func pop()->T?{
if depth > 0 {
return items.removeLast()
} else {
return nil
}
}
func generate() -> StackGenerator<T> {
return StackGenerator(stack: self)
}
}
struct StackGenerator<T>: GeneratorType {
typealias Element = T
var current = 0
var stack: Stack<T>
init (stack: Stack<T>) {
self.stack = stack
}
mutating func next() -> T? {
if current < self.stack.items.count {
return self.stack.items[current++] // Get an error here: can't access items in Stack
}
return nil
}
}