使用条件排名数组快速减少和求和

时间:2019-06-15 10:56:13

标签: ios swift iphone swift5

我想算出胜利的数目并加总所有积分。

我希望使用平面地图并进行简化,以减少复杂性。为了保证我可以用

问题是,在allMatch中,我可以有不同的teamID(团队可以单人或情侣玩),而顺序无关紧要(例如teamID 1,2等于teamID 2,1 < / p>

struct InfoMatch: Hashable {
    let teamId: Set<Int>
    let rank: Int
    let mPoints: Int
    let vPoints: Int
}

所有比赛都是由array组成的数组,因为它返回每场比赛的每支球队的信息,在本示例中,第一场比赛由2队完成,最后一场比赛由3队

let allMatch: [[InfoMatch]] = [
    [InfoMatch(teamId:[1,2],rank:1,mPoints: 200,vPoints: 0),InfoMatch(teamId:[3,4],rank:2,mPoints: 100,vPoints: 0)],
    [InfoMatch(teamId:[1,2],rank:2,mPoints: 0,vPoints: 10),InfoMatch(teamId:[4,3],rank:1,mPoints: 0,vPoints: 20)],
    [InfoMatch(teamId:[2,1],rank:1,mPoints: 40,vPoints: 0),InfoMatch(teamId:[3,4],rank:2,mPoints: 30,vPoints: 0),InfoMatch(teamId:[5,6],rank:3,mPoints: 5,vPoints: 0)]
]
let winners = allMatch.map{$0.filter{$0.rank == 1}}
let losers = allMatch.map{$0.filter{$0.rank != 1}}

print(winners)

打印:

  

[[__ lldb_expr_7.InfoMatch(teamId:Set([1,2]),等级:1,mPoints:200,   vPoints:0)],[__lldb_expr_7.InfoMatch(teamId:Set([3,4]),等级:1,   mPoints:0,vPoints:20)],[__lldb_expr_7.InfoMatch(teamId:Set([1,   2]),排名:1,mPoints:40,vPoints:0)]]

我想要一个返回的数组

teamID: victoryCount: loserCount: mPoints: vPoints:

例如:

  

teamID:1,2胜利数:2失败者数:1积分:240积分:10   teamID:3,4 victoryCount:1失败者Count:2 mPoints:130 vPoints:20   teamID:5,6 victoryCount:0 lossrCount:1 mPoints:5 vPoints:0

1 个答案:

答案 0 :(得分:0)

我真的想知道使用 flatmap map和reduce 是否可以降低复杂度,但是您可以以这种方式使用reduce

首先,您说要 teamID:victoryCount:LoserCount:mPoints:vPoints:,那么最好定义代表它的类型:

struct MatchStats {
    var teamID: Set<Int>
    var victoryCount: Int
    var loserCount: Int
    var mPoints: Int
    var vPoints: Int
}

//For convenience...
extension MatchStats {
    init(teamID: Set<Int>) {
        self.teamID = teamID
        victoryCount = 0
        loserCount = 0
        mPoints = 0
        vPoints = 0
    }
}

//For debugging...
extension MatchStats: CustomStringConvertible {
    public var description: String {
        let teamIDStr = teamID.sorted().map(String.init).joined(separator: ",")
        return "teamID:\(teamIDStr) victoryCount:\(victoryCount) loserCount:\(loserCount) mPoints:\(mPoints) vPoints:\(vPoints)"

    }
}

并在reduceflatMap中按以下方式使用它:

let teamStats: [Set<Int>: MatchStats] = allMatch.flatMap{$0}.reduce(into: [:]) {result, info in
    result[info.teamId, default: MatchStats(teamID: info.teamId)].victoryCount += info.rank == 1 ? 1 : 0
    result[info.teamId]!.loserCount += info.rank == 1 ? 0 : 1
    result[info.teamId]!.mPoints += info.mPoints
    result[info.teamId]!.vPoints += info.vPoints
}

print(teamStats.values)

输出:

[teamID:1,2 victoryCount:2 loserCount:1 mPoints:240 vPoints:10, teamID:3,4 victoryCount:1 loserCount:2 mPoints:130 vPoints:20, teamID:5,6 victoryCount:0 loserCount:1 mPoints:5 vPoints:0]

(输出在每次调用时可能是随机的。但是对它进行排序是另一个问题。)


您认为使用reduce比这更好吗?

var teamStats: [Set<Int>: MatchStats] = [:]
for match in allMatch {
    for info in match {
        teamStats[info.teamId, default: MatchStats(teamID: info.teamId)].victoryCount += info.rank == 1 ? 1 : 0
        teamStats[info.teamId]!.loserCount += info.rank == 1 ? 0 : 1
        teamStats[info.teamId]!.mPoints += info.mPoints
        teamStats[info.teamId]!.vPoints += info.vPoints
    }
}

print(teamStats.values)