2

I am using swapi.co as my source of json data and my response looks like the following: https://swapi.co/api/people/

My array of "characters" has the structure

// MARK: - CharactersResult
struct CharactersResult: Codable {
    let name, height, mass, hairColor: String
    let skinColor, eyeColor, birthYear: String
    let gender: Gender
    let homeworld: String
    let films, species, vehicles, starships: [String]
    let created, edited: String
    let url: String

    enum CodingKeys: String, CodingKey {
        case name, height, mass
        case hairColor = "hair_color"
        case skinColor = "skin_color"
        case eyeColor = "eye_color"
        case birthYear = "birth_year"
        case gender, homeworld, films, species, vehicles, starships, created, edited, url
    }
}

I would like to get the smallest character and the largest out of my array. My function is:

func getCharacters(urlToGet: String){
            do{
                if let url = URL(string: urlToGet) {
                    URLSession.shared.dataTask(with: url) { data, response, error in
                        if let data = data {
                            do {
                                let jsonCharacters = try JSONDecoder().decode(Characters.self, from: data)



                                self.characters = self.characters + jsonCharacters.results

                                self.nextPageUrlForCharacters = jsonCharacters.next

                                self.updatePicker()

                            } catch let error {
                                print(error)


                            }
                        }
                        }.resume()

                }
            }
        }

My main question is where to do the sorting and what is the most efficient way to get the smallest and the largest character.

1
  • You want to get all of your results and then use the reduce function to get the smallest or largest. What do you mean by length? What makes a CharactersResult short or long? Commented Sep 3, 2019 at 18:28

2 Answers 2

3

Assuming smallest and largest is related to the height of the character (then shortest and tallest are more appropriate), sort the array by that struct member. As the value is String you have to add the .numeric option.

The descending order starts with the largest value

let sortedCharacters = self.characters.sorted{$0.height.compare($1.height, options: .numeric) == .orderedDescending}
let tallestCharacter = sortedCharacters.first
let shortestCharacter = sortedCharacters.last

Side note: You can get rid of the CodingKeys if you add the convertFromSnakeCase key decoding strategy.

Sign up to request clarification or add additional context in comments.

Comments

0

This simplified version of your code illustrates how to sort by an arbitrary key, as long as that key is Comparable (so I've made your height and mass properties both Ints rather than String):

struct MovieCharacter: Codable {
    let name: String
    let height: Int
    let mass: Int
}

let fred = MovieCharacter(name: "Fred", height: 123, mass: 99)
let wilma = MovieCharacter(name: "Wilma", height: 158, mass: 47)

let chars = [fred, wilma]

let heaviestToLightest = chars.sorted { $0.mass > $1.mass }
// Prints "Fred, Wilma"
print(heaviestToLightest.map { $0.name }.joined(separator: ", "))

let tallestToShortest = chars.sorted { $0.height > $1.height }
// prints "Wilma, Fred"
print(tallestToShortest.map { $0.name }.joined(separator: ", "))

To change the sort order, reverse the >' in the comparison closure. If you want to know the "most" and "least" of a particular order, use.firstand.last` on the result.

Also, to save yourself from having to maintain the CodingKeys enum, use .keyDecodingStrategy of a JSONDecoder:

let decoder = JSONDecoder()
decoder.keyDecodingStrategy = .convertFromSnakeCase
let characters = try decoder.decode(Characters.self, from: jsonData)

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.