arrays - Swift map and filter: Find all factories that are not owned by a given player -
i have swift playground file have list of factories child entities called engines; player can hold many engines
the relationship thus;
factory -> engine <- player
- one factory has many engines
- one player has many engines
- one engine has single parent (factory)
- one engine has single owner (player)
i'm trying build swift map , filter where, produces list of factories not owned given player object.
my code follows;
//: swift playground code import foundation class factory : customstringconvertible { var name: string = "" var engines: [engine] = [engine]() var description: string { return self.name } var owners: [player]? { let filtered = self.engines.filter { (eng:engine) -> bool in return (eng.owner != nil) } .sorted { (enga:engine, engb:engine) -> bool in return ((enga.owner?.turnorder)! < (engb.owner?.turnorder)!) }.flatmap { (eng:engine) -> player? in return (eng.owner) } return filtered } init(name: string) { self.name = name // create 3 children (engines) _ in 1...3 { let engine = engine.init(parent: self) self.engines.append(engine) } } } class engine : customstringconvertible { weak var parent: factory? weak var owner: player? var description: string { guard let hasparent = self.parent else { return "n/a" } return ("\(hasparent.name) - engine") } init(parent: factory) { self.parent = parent } func setowner(owner: player) { self.owner = owner self.owner?.addengine(engine: self) } } class player : customstringconvertible { var name: string = "" var engines: [engine] = [engine]() var turnorder: int = 0 var description: string { return self.name } init(name: string) { self.name = name } func addengine(engine: engine) { self.engines.append(engine) } } // create 3 factories let f1 = factory.init(name: "f1") let f2 = factory.init(name: "f2") let f3 = factory.init(name: "f3") let factories = [f1,f2,f3] let p1 = player.init(name: "bob") if let firstengine = f1.engines.first { firstengine.setowner(owner: p1) } print ("all factories: \(factories)") print ("p1 = \(p1.name), engines: \(p1.engines)") (index, f) in factories.enumerated() { print ("#\(index), owners: \(f.owners)") } // filter factories not owned player let filtered = factories.map({ $0.engines.filter({ (eng: engine) -> bool in return (eng.owner != nil) })}) print ("factories not owned player") print (filtered) the output follows:
all factories: [f1, f2, f3] p1 = bob, engines: [f1 - engine] #0, owners: optional([bob]) #1, owners: optional([]) #2, owners: optional([]) factories not owned player [[f1 - engine], [], []] the issue i'm having last filter code;
// filter factories not owned player let filtered = factories.map({ $0.engines.filter({ (eng: engine) -> bool in return (eng.owner != nil) })}) this returns factories engines not nil,
i wish use:
return (eng.owner != p1)
but error returned;
error: cannot convert value of type 'player' expected argument type '_optionalnilcomparisontype' return (eng.owner != p1) i'm wondering, how can filter map of factories , return list of factories given player not own?
many thanks
i think you're looking for:
extension factory { func isowned(by player: player?) -> bool { return self.engines.contains(where: { $0.isowned(by: player)} ) } } extension engine { func isowned(by player: player?) -> bool { return self.owner === player } } let factoriesnotownedbyp1 = factories.filter { !$0.isowned(by: p1) } and here other changes make existing code:
import foundation class factory { let name: string var engines = [engine]() init(name: string) { self.name = name self.engines += (1...3).map{ _ in engine(parent: self) } } var owners: [player]? { return self.engines .lazy .flatmap { engine in engine.owner.map{ (engine: engine, owner: $0) } } .sorted { $0.owner.turnorder < $1.owner.turnorder } .map { $0.owner } } func isowned(by player: player?) -> bool { return self.engines.contains(where: { $0.isowned(by: player)} ) } } extension factory: customstringconvertible { var description: string { return self.name } } class engine { weak var parent: factory? weak var owner: player? init(parent: factory) { self.parent = parent } func setowner(owner: player) { self.owner = owner self.owner?.addengine(engine: self) } } extension engine: customstringconvertible { var description: string { guard let parent = self.parent else { return "n/a" } return ("\(parent.name) - engine") } } class player { let name: string var engines = [engine]() var turnorder = 0 init(name: string) { self.name = name } func addengine(engine: engine) { self.engines.append(engine) } } extension player: customstringconvertible { var description: string { return self.name } } let factories = [ factory(name: "f1"), factory(name: "f2"), factory(name: "f3"), ] let p1 = player(name: "bob") factories.first?.engines.first?.setowner(owner: p1) print ("all factories: \(factories)") print ("p1 = \(p1.name), engines: \(p1.engines)") (index, f) in factories.enumerated() { print("#\(index), owners: \(string(describing: f.owners))") } let factoriesnotownedbyp1 = factories.filter { !$0.isowned(by: p1) } print("factories not owned player: ") print(factoriesnotownedbyp1)
Comments
Post a Comment