首页 > 解决方案 > 从 json 中获取单个元素

问题描述

我有一个看起来像这样的 json 响应:

{
    "Matches":[
        {
            "id": 1,
            "Teams": [
                {"id": 1, "score": 254},
                {"id": 2, "score": 253}
            ]
        },
        {
            "id": 2,
            "Teams": [
                {"id": 1, "score": 330},
                {"id": 3, "score": 331}
            ]
        },
        {
            "id": 3,
            "Teams": [
                {"id": 1, "score": 220},
                {"id": 4, "score": 220}
            ]
        },
        {
            "id": 4,
            "Teams": [
                {"id": 1, "score": 264},
                {"id": 5, "score": 189}
            ]
        },
        {
            "id": 5,
            "Teams": [
                {"id": 2, "score": 240},
                {"id": 3, "score": 200}
            ]
        },
        {
            "id": 6,
            "Teams": [
                {"id": 2, "score": 330},
                {"id": 4, "score": 331}
            ]
        },
        {
            "id": 7,
            "Teams": [
                {"id": 2, "score": 320},
                {"id": 5, "score": 220}
            ]
        },
        {
            "id": 8,
            "Teams": [
                {"id": 3, "score": 320},
                {"id": 4, "score": 300}
            ]
        },
        {
            "id": 9,
            "Teams": [
                {"id": 3, "score": 280},
                {"id": 5, "score": 300}
            ]
        },
        {
            "id": 10,
            "Teams": [
                {"id": 4, "score": 180},
                {"id": 5, "score": 180}
            ]
        }
    ]
}

这是我对上述响应的结构:

struct Matches: Codable {
    let matches: [Match]

    enum CodingKeys: String, CodingKey {
        case matches = "Matches"
    }
}

// MARK: - Match
struct Match: Codable {
    let id: Int
    let teams: [Team]

    enum CodingKeys: String, CodingKey {
        case id
        case teams = "Teams"
    }
}

// MARK: - Team
struct Team: Codable {
    let id, score: Int
}

这就是我进行 api 调用以获取数据的方式:

fileprivate func getMatches() {
    URLSession.shared.dataTask(with: URL(string: "URL HERE")!) { (data, response, error) in
        guard let data = data else { return }
        do {
            let res = try JSONDecoder().decode(Matches.self, from: data)

        }
        catch {
            print(error)
        }
        }.resume()
}

但我无法弄清楚的是如何比较响应中 2 个 id 的分数,Teamsjson说出哪个 id 更大以及每个 id 的计数。

标签: iosjsonswift

解决方案


1队比赛:

let team1 = res.matches.filter {$0.teams.contains { $0.id == 1 }}

找到每场比赛的获胜者,使用这个扩展:

extension Match {
    var winnerTeam: Team {
        return teams.sorted { $0.score > $1.score }.first!
    }
}

例如,获胜者的数组如下:

let winners = res.matches.map { $0.winnerTeam }

类似地寻找更松散的团队:

extension Match {
    var looserTeam: Team {
        return teams.sorted { $0.score > $1.score }.last!
    }
}

按 id 计算获胜团队:

func scoresOfWinners() -> [Int: Int] {
    var scores = [Int: Int]()
    for team in winners {
        scores[team.id] = (scores[team.id] ?? 0) + 1
    }
    return scores
}

它将返回一个 id 列表:win count。

请记住,如果您想处理tie这种情况,您应该在选择赢家或更松之前进行防范,如下所示:

var winnerTeam: Team? {
    guard teams.first!.score != teams.last!.score else { return nil }
    return teams.sorted { $0.score > $1.score }.first!
}

推荐阅读