Looping through array and switch

I'm getting array of Int, which is film genres, and I need to give to each element corresponding genre (for example: 28 - "Action", 12 - "Adventure") and display them in tableView cell.

I tried to write func, which accepts array of genres, then loops through array and returns corresponding genre by switch but I'm getting two errors "Variable 'genre' used before being initialized" and "Missing return in a function expected to return 'String".

Could you please help me fix code and give some recommendations about how to properly get a genre.

func getGenre(filmGenres: [Int]) -> String {
  
  var genre: String
    
  for i in filmGenres {
    
    switch i {
    case 28:
        genre = "Action"
    case 12:
        genre = "Adventure"
    case 16:
        genre = "Animation"
    case 35:
        genre = "Comedy"
    case 80:
        genre = "Crime"
    case 99:
        genre = "Documentary"
    case 18:
        genre = "Drama"
    case 10751:
        genre = "Family"
    case 14:
        genre = "Fantasy"
    case 36:
        genre = "History"
    case 27:
        genre = "Horror"
    case 10402:
        genre = "Music"
    case 9648:
        genre = "Mystery"
    case 10749:
        genre = "Romance"
    case 878:
        genre = "Science Fiction"
    case 10770:
        genre = "TV Movie"
    case 53:
        genre = "Thriller"
    case 10752:
        genre = "War"
    case 37:
        genre = "Western"
    default:
        return ""
    }
}
     return genre
}

For starters you have too many closing-brackets.

Next, your function takes in an array of numbers but only returns a single string.

Perhaps a simpler design would take in one number and return the string for that number.

Then if you have an array of numbers, you can loop through (or map over) the array, calling the single-input version of the function for each value.

2 Likes

Thank you. I'll try your method.

This is not what you're asking, but I think it might be good to replace the switch cases with a dictionary:

let genres = [28: "Action", 12: "Adventure", /* ... */]

It also seems like that you want the output to be an array of string instead of a single string.

Then, combined with @Nevin's suggestion, you can do the entire thing in one line with compactMap():

filmGenres.compactMap { genres[$0] }
// Use compactMap because the the dictionary subscript returns Optional<String> 
3 Likes

You could also try creating an enum to do the conversion

enum Genre: Int {
    case action = 28
    case adventure = 12
    case animation = 16
    case comedy = 35
    case crime = 80
    case documentary = 99
    case drama = 18
    case family = 10751
    case fantasy = 14
    case history = 36
    case horror = 27
    case music = 10402
    case mystery = 9648
    case romance = 10749
    case scienceFiction = 878
    case tvMovie = 10770
    case thriller = 53
    case war = 10752
    case western = 37

    var description: String {
        switch self {
        case .action: return "Action"
        case .adventure: return "Adventure"
        case .animation: return "Animation"
        case .comedy: return "Comedy"
        case .crime: return "Crime"
        case .documentary: return "Documentary"
        case .drama: return "Drama"
        case .family: return "Family"
        case .fantasy: return "Fantasy"
        case .history: return "History"
        case .horror: return "Horror"
        case .music: return "Music"
        case .mystery: return "Mystery"
        case .romance: return "Romance"
        case .scienceFiction: return "Science Fiction"
        case .tvMovie: return "TV Movie"
        case .thriller: return "Thriller"
        case .war: return "War"
        case .western: return "Western"
        }
    }
}

let genres = [28, 12, 16].compactMap { Genre(rawValue: $0) }
print(genres.map(\.description)) // ["Action", "Adventure", "Animation"]
2 Likes

Thank you @wowbagger @jflan! I tried both solutions but choose to use this code from stackoverflow.

let genreIds = [28, 12, 99, 12]

// Just to make sure we have unique genres. 
// You may skip this if your application logic ensures this
let uniqGenreIds = Array(Set(genreIds))  

// Create an sorted array with the textual genre names:
let stringGenres = uniqGenreIds.map {
    (intGenre) -> String in
    switch intGenre {
        case 28:
            return "Action"
        case 12:
            return "Adventure"
        case 16:
            return "Animation"
        default: return "unknown"
    }
}.sorted()

// Join the strings:
let allGenres = stringGenres.joined(separator: ",")
print (allGenres) // Action,Adventure,unknown

It's cool that now I know to solve this task using a dictionary, enums and switch. Once again thank you for your help! :raised_hands:

One very, very minor thing, you don't need to recreate Array when creating uniqGenreIds (should be uniqGenreIDs per API design guideline). Set itself also has a map function, so you can use Set just fine. It could save you time when the array itself is large because you don't need to copy data from the set over to an array, but probably won't matter much at this scale.

1 Like