0

In my json result, there is odds array. And inside of it, there will be 8 types of bet. And i want to sort the array by bet type as i want to show. Eg. first "name": "3Way Result", second another one, third "over/under" etc..

Here is my json result from server.

 {
    "success": true,
    "result": [
        {
            "league_id": 5,
            "localTeam": {"data": {}},
            "visitorTeam": {"data": {}},
            "scores": {},
            "time": {"starting_at": {},},
            "league": {"data": {"coverage": {}}},
            "odds": [
                {
                    "id": 12,
                    "name": "Over/Under",
                    "suspended": false,
                    "bookmaker": {
                        "data": [
                            {
                                "id": 2,
                                "name": "bet365",
                                "odds": {
                                    "data": [
                                        {
                                            "label": "Over",
                                            "value": "2.00",
                                            "extra": null,
                                            "probability": "50%",
                                            "dp3": "2.000",
                                            "american": 100,
                                            "handicap": null,
                                            "total": "2.5",
                                            "winning": null,
                                            "stop": false,
                                            "bookmaker_event_id": 84922729,
                                        },
                                        {
                                            "label": "Under",
                                            "value": "1.80",
                                            "probability": "55.56%",
                                            "dp3": "1.800",

                                        }
                                    ]
                                }
                            }
                        ]
                    }
                },
                {
                    "id": 1,
                    "name": "3Way Result",
                    "suspended": false,
                    "bookmaker": {
                        "data": [
                            {
                                "id": 2,
                                "name": "bet365",
                                "odds": {
                                    "data": [
                                        {
                                            "label": "1",
                                            "value": "2.10",
                                            "extra": null,
                                            "probability": "47.62%",
                                            "dp3": "2.100",
                                            "american": 110,

                                        },
                                        {
                                            "label": "X",
                                            "value": "3.30",
                                            "extra": null,
                                            "probability": "30.3%",
                                            "dp3": "3.300",
                                            "american": 229,

                                        },
                                        {
                                            "label": "2",
                                            "value": "3.60",

                                        }
                                    ]
                                }
                            }
                        ]
                    }
                },
                {
                    "id": 975909,
                    "name": "Correct Score",
                    "suspended": false,
                    "bookmaker": {
                        "data": [
                            {
                                "id": 2,
                                "name": "bet365",
                                "odds": {
                                    "data": [
                                        {
                                            "label": "1:0",
                                            "value": "7.50",
                                            "extra": null,
                                            "probability": "13.33%",
                                            "dp3": "7.500",
                                            "american": 650,
                                            "factional": null,
                                            "handicap": null,
                                            "total": null,
                                            "winning": null,
                                            "stop": false,
                                            "bookmaker_event_id": 84922729,
                                            "last_update": {
                                                "date": "2020-02-20 10:59:06.746514",
                                                "timezone_type": 3,
                                                "timezone": "UTC"
                                            }
                                        },
                                        {
                                            "label": "2:0",
                                            "value": "10.00",

                                        },

                                    ]
                                }
                            }
                        ]
                    }
                },


            ],
            "tipsters": 2
        }
    ]
} 

so it is not alphabetically, datetime or anytype i could access. How could i do ?

Update: I have added model.

struct BetterMatchResults: APIModel, Codable {
    var success: Bool?
    var result: [BetterMatch]?
}
struct BetterMatch: APIModel, Codable  {
    var id,_id: String?
    var localTeam, visitorTeam: BetterTeam?
    var spId, league_id, seasonID: Int?
    var winningOddsCalculated: Bool?
    var time: BetterTime?
    var league: BetterLeague?
    var createdAt, updatedAt: String?
    var odds: [BetterOdd]!
    var resultID: String?
    var tipsters: Int?
    var stats_url: String?
}

struct BetterLeague : APIModel, Codable {
    var data: LeagueData?
}

struct LeagueData : APIModel, Codable{
    var id: Int?
    var active: Bool?
    //var legacyID, countryID: Int?
    var logo_path: String?
    var name: String?
    //var isCup: Bool?

}

struct BetterOdd : APIModel, Codable {
    var id: Int?
    var name: String?
    var suspended: Bool?
    var bookmaker: BetterBookmaker?
   }

// MARK: - Bookmaker
struct BetterBookmaker : APIModel, Codable {
    var data: [BetterBookmakerDatum]?
}

// MARK: - BookmakerDatum
struct BetterBookmakerDatum : APIModel, Codable {
    var id: Int?
    var name: String?
    var odds: BetterOdds?
}

// MARK: - Odds
struct BetterOdds : APIModel, Codable {
    var data: [BetterOddsDatum]?
}

class BetterOddsDatum: APIModel , Codable {

    var label: String?
     //var extra: NSNull?
     //var probability, dp3: String?
     var american: Int?
     //var factional, handicap: NSNull?
     var total: String?
     var winning: Bool?
     var stop: Bool?
     var bookmakerEventID: Int?
    //private var odd: Double
    public var value: String?
    init() {

    }
}
Adem Özsayın
  • 245
  • 2
  • 14

3 Answers3

2

If I understand your question correctly you want to be able sort the data based on betting type but the value of betting types are not sortable if used as a String variable. The solution would be to converting them into enum types with raw values and then sorting the array based on those raw values. Here is an example:

// Create a BetType for your datas
enum BetType: Int {
  case overUnder = 0
  case threeWayResult = 1 // 3WayResult
  ...
}

// Update your BetterOdd
struct BetterOdd : APIModel, Codable {
    var id: Int?
    var name: String?
    var betType: BetType = .overUnder // or put your default value here
    var suspended: Bool?
    var bookmaker: BetterBookmaker?
   }

// Loop your BetterMatch property's odds value after fetching datas.
for i in 0..<betterMatch.odds {
   if betterMatch.odds[i].name == "over/under" {
      betterMatch.odds[i].betType = .overUnder
   }
   ... // Do the same for other types as well in else if blocks 
}

Another alternative would be to add a function for getting the type in BetterOdd

struct BetterOdd ... {
  ... // Your properties

  func getBetType() -> BetType {
    if name == "over/under" {
       return .overUnder
    } else if name == "3WayResult" {
       return .threeWayResult
    }
    ... // Other cases
  }
}

Finnaly for sorting you can do:

let result = betterMatch.odds.sorted({ $0.betType.rawValue > $1.betType.rawValue })
// or if you used the function solution
let result = betterMatch.odds.sorted({ $0.getBetType().rawValue > $1.getBetType().rawValue })

Since you are using a Codable approach you might need to loop the array and set the betType values based on name values.

Ayazmon
  • 1,360
  • 8
  • 17
  • You understand correctly but there is a issue. case can not start with number so it says in editor "'W' is not a valid digit in integer literal". How to match if it is 3 way result or Correct Score etc.. – Adem Özsayın Feb 20 '20 at 12:42
  • Oh that's my bad `case 3WayResult ` is not valid try to use it as `case threeWayResult`. Enum cases can't start with numbers. I've updated my answer accordingly. – Ayazmon Feb 20 '20 at 12:44
  • then how to know if threeWayResult is 3 Way Result in my array? – Adem Özsayın Feb 20 '20 at 12:45
  • I've updated my answer to fit this need. Like I said since you are using `Codable` the code can't parse your JSON data into an `enum` thus you need to set the `betType` value manually. – Ayazmon Feb 20 '20 at 12:49
1

i changed model

struct BetterOdd : APIModel, Codable {
    var id: Int?
    var name: String?
    var suspended: Bool?
    var bookmaker: BetterBookmaker?
    //var betType: BetType = .threeWayResult

    enum BetType:Int, APIModel, Codable {
        case threeWayResult = 7
        case overUnder = 6
        case doubleChance = 5
        case bothTeamsToScore = 4
        case threeWayResultFirstHalf = 3
        case threeWayResultSecondHalf = 2
        case correctScore = 1
        case hTfTdouble = 0
    }
//
    func getBetType() -> BetType {
        if name == "3Way Result" {
            return .threeWayResult
        } else if name == "Over/Under" {
            return .overUnder
        } else if name == "Double Chance"  {
            return .doubleChance
        } else if name == "Both Teams To Score"  {
            return .bothTeamsToScore
        } else if  name == "3Way Result 1st Half" {
            return .threeWayResultFirstHalf
        } else if name == "3Way Result 2nd Half"{
            return .threeWayResultSecondHalf
        } else if name == "Correct Score"{
            return .correctScore
        } else if name == "HF/FT Double" {
            return .hTfTdouble
        } else {
            return .correctScore
        }
    }
}

and then :

let matchOddsArray  = match.odds!
let result = matchOddsArray.sorted(by: { $0.betType.rawValue > $1.betType.rawValue})
let bet = result[indexPath.row]

works perfect.

Adem Özsayın
  • 245
  • 2
  • 14
0

First of all, mark result in BetterMatchResults and odds in BetterMatch as var, i.e.

struct BetterMatchResults: Codable {
    let success: Bool
    var result: [BetterMatch] //here....
}

struct BetterMatch: Codable {
    var odds: [BetterOdd] //here....
    //rest of the parameters...
}

Next, while parsing your JSON data, use map(_:) and sorted(by:) to modify the result and odds in the betterMatchResults, i.e.

do {
    let decoder = JSONDecoder()
    decoder.keyDecodingStrategy = .convertFromSnakeCase
    var betterMatchResults = try JSONDecoder().decode(BetterMatchResults.self, from: data)

    betterMatchResults.result = betterMatchResults.result.map {(betterMatch) in
        var match = betterMatch
        match.odds =  match.odds.sorted(by: { $0.name < $1.name })
        return match
    }

    //Test the response...
    print(betterMatchResults.result.map({ $0.odds.map({ $0.name }) })) //[["3Way Result", "Correct Score", "Over/Under"]]

} catch {
    print(error)
}
PGDev
  • 23,751
  • 6
  • 34
  • 88
  • Ayazman's answer solved the problem. Since i use callback for fetching data i didn't want to change network class. Thanks anyway. – Adem Özsayın Feb 20 '20 at 14:35