代码之家  ›  专栏  ›  技术社区  ›  zardon

快速映射和筛选:查找所有不属于给定玩家的工厂

  •  0
  • zardon  · 技术社区  · 9 年前

    Factory -> Engine <- Player

    • 一个玩家有多个引擎
    • 一个引擎只有一个所有者(玩家)

    我正试图建立一个快速的地图和过滤器,其中,它产生了一个列表,所有工厂是 不 由给定玩家对象拥有。

    //: 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)
            for _ 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)")
    
    for (index, f) in factories.enumerated() {
        print ("#\(index), Owners: \(f.owners)")
    }
    
    // filter all factories NOT owned by player
    
    let filtered = factories.map({ $0.engines.filter({ (eng: Engine) -> Bool in
            return (eng.owner != nil)
        })})
    
    print ("factories not owned by player")
    
    print (filtered)
    

    输出如下:

    All factories: [f1, f2, f3]
    p1 = Bob, engines: [f1 - engine]
    #0, Owners: Optional([Bob])
    #1, Owners: Optional([])
    #2, Owners: Optional([])
    factories not owned by player
    [[f1 - engine], [], []]
    

    我遇到的问题是最后一个过滤代码;

    // filter all factories NOT owned by player
    
    let filtered = factories.map({ $0.engines.filter({ (eng: Engine) -> Bool in
            return (eng.owner != nil)
        })})
    

    这只会返回发动机不为零的工厂,

    return (eng.owner != p1)

    但返回错误;

    error: cannot convert value of type 'Player' to expected argument type '_OptionalNilComparisonType'
            return (eng.owner != p1)
    

    因此,我想知道,我如何过滤工厂的地图,并只返回一个给定的球员所做的所有工厂的列表 不

    2 回复  |  直到 9 年前
        1
  •  1
  •   Alexander    9 年前

    我想这就是你想要的:

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

    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)")
    
    for (index, f) in factories.enumerated() {
        print("#\(index), Owners: \(String(describing: f.owners))")
    }
    
    
    let factoriesNotOwnedByP1 = factories.filter { !$0.isOwned(by: p1) }
    
    print("factories not owned by player: ")
    print(factoriesNotOwnedByP1)
    
        2
  •  0
  •   Casper Zandbergen    9 年前

    你需要告诉斯威夫特是什么类型的。所有者是:

    let filtered = factories.map({ $0.engines.filter({ (eng: Engine) -> Bool in
        return (eng.owner as? Player != p1)
    })})
    

    编辑:实际上可能是需要设置为播放器的“p1”,错误消息没有指定。