Find an element in a stack data structure swift 4 - swift

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"),]
}

Related

How can I get a specific struct type returned?

I want to initialize the struct by receiving the "struct type"(?) by a specific logic as below.
As I abstracted the return value of the struct into MyProtocol had a declaration of init(), which seems a little awkward.
I'm not sure I can do this.
I'd like to get an undecided struct type returned, what should I do?
Is this for the best?
For your information, Opaque Type is not available because it needs to support iOS 13 or earlier.
protocol MyProtocol {
init() // Is this for the best?
}
struct AAA: MyProtocol {
var numberAAA: Int // Sample variable.
init() {
print("init AAA")
numberAAA = 100
}
}
struct BBB: MyProtocol {
var numberBBB: Int // Sample variable.
init() {
print("init BBB")
numberBBB = 200
}
}
class MyClass {
func mainLogic() {
let myStruct = randomStruct()
myStruct.init() // This is the reason init () declared in the MyProtocol.
}
func randomStruct() -> MyProtocol.Type {
if Bool.random() {
return AAA.self
} else {
return BBB.self
}
}
}
init() as a protocol requirement seems odd. No one is stopping you to do this and compiler should allow this, however I would consider making protocol based on some other requirement rather than just init().
Here's an attempt to do so -
protocol NumberOperation {
var number: Int { get set }
mutating func perform()
}
struct Incrementer: NumberOperation {
var number: Int
mutating func perform() {
number += 1
}
}
struct Decrementer: NumberOperation {
var number: Int
mutating func perform() {
number -= 1
}
}
struct Record<O: NumberOperation> {
public var operation: O
mutating func perform() {
operation.perform()
}
}
class MyClass {
func mainLogic() {
var record = getRecord(type: Incrementer.self)
record.perform()
}
func getRecord<O: NumberOperation>(type: O.Type) -> Record<O> {
if type == Incrementer.self {
return Record(operation: Incrementer(number: 1) as! O)
}
return Record(operation: Decrementer(number: 10) as! O)
}
}
This introduces a container type Record that holds/wraps our type based on the same protocol conformation. This does the same what you were doing, probably is easier to read/understand.

Is there a built in stack implementation in 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

WeakBox requires that WeakArray<Element>.Element be a class type

I'm trying to implement a storing weak references solutions from objc talks (https://www.objc.io/blog/2017/12/28/weak-arrays/) but I'm not able to get it working.
The exact error message tells:
'WeakBox' requires that 'WeakArray<Element>.Element' (aka 'Optional<Element>') be a class type
With this code:
final class WeakBox<A: AnyObject> {
weak var unbox: A?
init(_ value: A) {
unbox = value
}
}
struct WeakArray<Element: AnyObject> {
private var items: [WeakBox<Element>] = []
init(_ elements: [Element]) {
items = elements.map { WeakBox($0) }
}
init() {}
}
extension WeakArray: Collection {
var startIndex: Int { return items.startIndex }
var endIndex: Int { return items.endIndex }
subscript(_ index: Int) -> Element? {
return items[index].unbox
}
func index(after idx: Int) -> Int {
return items.index(after: idx)
}
mutating func append(_ element: Element) {
items.append(WeakBox(element))
}
mutating func removeAll() {
items.removeAll()
}
}
**
Update:
**
After some time I realized that error message is completely misleading. The real problem is in calling methods of a Sequence protocol. For example, adding something like this below produces an error message from the above screenshot. But I haven't found a solution yet.
class De {
let de = "de"
}
let de = De()
var ar = WeakArray<De>([])
ar.append(de)
ar.append(de)
ar.forEach({ $0 })
I believe 'Element' is being redefined by the SDK somewhere. Renaming Element to T should fix the issue.
import Foundation
final class WeakBox<T:AnyObject> {
weak var unbox: T?
init(_ value: T?) {
unbox = value
}
}
struct WeakArray<T: AnyObject> {
private var items: [WeakBox<T>] = []
init(_ elements: [T]) {
items = elements.map { WeakBox($0) }
}
init(_ elements: [T?]) {
items = elements.map { WeakBox($0) }
}
mutating func append(_ obj:T?) {
items.append(WeakBox(obj))
}
mutating func remove(at:Int) {
items.remove(at: at)
}
}
extension WeakArray: Collection {
var startIndex: Int { return items.startIndex }
var endIndex: Int { return items.endIndex }
subscript(_ index: Int) -> T? {
return items[index].unbox
}
func index(after idx: Int) -> Int {
return items.index(after: idx)
}
}

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
}
}