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.

asked Sep 3, 2019 at 18:15
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.

answered Sep 3, 2019 at 18:57

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)
answered Sep 3, 2019 at 18:48

Comments

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

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.