0

I am attempting to find each instance of the string name: being different.

As for the example of JSON below I want to pull Alamo Draft House Lamar and Alamo Draft House Ritz and place them into an array.

JSON:

[{
"tmsId": "MV011110340000",
"rootId": "15444050",
"subType": "Feature Film",
"title": "Bohemian Rhapsody",
"releaseYear": 2018,
"releaseDate": "2018-11-02",
"titleLang": "en",
"descriptionLang": "en",
"entityType": "Movie",
"genres": ["Biography", "Historical drama", "Music"],
"longDescription": "Singer Freddie Mercury, guitarist Brian May, drummer Roger Taylor and bass guitarist John Deacon take the music world by storm when they form the rock 'n' roll band Queen in 1970. Surrounded by darker influences, Mercury decides to leave Queen years later to pursue a solo career. Diagnosed with AIDS in the 1980s, the flamboyant frontman reunites with the group for Live Aid -- leading the band in one of the greatest performances in rock history.",
"shortDescription": "Singer Freddie Mercury of Queen battles personal demons after taking the music world by storm.",
"topCast": ["Rami Malek", "Lucy Boynton", "Gwilym Lee"],
"directors": ["Bryan Singer"],
"officialUrl": "https://www.foxmovies.com/movies/bohemian-rhapsody",
"ratings": [{
    "body": "Motion Picture Association of America",
    "code": "PG-13"
}],
"advisories": ["Adult Language", "Adult Situations"],
"runTime": "PT02H15M",
"preferredImage": {
    "width": "240",
    "height": "360",
    "uri": "assets/p15444050_v_v5_as.jpg",
    "category": "VOD Art",
    "text": "yes",
    "primary": "true"
},
"showtimes": [{
    {
    "theatre": {
        "id": "9489",
        "name": "Alamo Drafthouse at the Ritz"
    },
    "dateTime": "2018-11-10T19:15",
    "barg": false,
    "ticketURI": "http://www.fandango.com/tms.asp?t=AAUQP&m=185586&d=2018-11-10"
}, {
    "theatre": {
        "id": "9489",
        "name": "Alamo Drafthouse at the Ritz"
    },
    "dateTime": "2018-11-10T22:30",
    "barg": false,
    "ticketURI": "http://www.fandango.com/tms.asp?t=AAUQP&m=185586&d=2018-11-10"
}, {
    "theatre": {
        "id": "5084",
        "name": "Alamo Drafthouse South Lamar"
    },
    "dateTime": "2018-11-10T12:00",
    "barg": false,
    "ticketURI": "http://www.fandango.com/tms.asp?t=AATHS&m=185586&d=2018-11-10"
}, {
    "theatre": {
        "id": "5084",
        "name": "Alamo Drafthouse South Lamar"
    },
    "dateTime": "2018-11-10T15:40",
    "barg": false,
    "ticketURI": "http://www.fandango.com/tms.asp?t=AATHS&m=185586&d=2018-11-10"
},
}]
}]

Here is my api code:

var shows = [Shows]()

struct Shows: Codable {
    let showtimes: [Showtimes]

    struct Showtimes: Codable {
    let theatre: Theater

        struct Theater: Codable {
            let id: String
            let name: String
        }

    }
}

func loadShowtimes() {

    let apiKey = ""
    let today = "2018-11-10"
    let zip = "78701"
    let filmId = "MV011110340000"
    let radius = "15"
    let url = URL(string: "http://data.tmsapi.com/v1.1/movies/\(filmId)/showings?startDate=\(today)&numDays=5&zip=\(zip)&radius=\(radius)&api_key=\(apiKey)")
    let request = URLRequest(
        url: url! as URL,
        cachePolicy: URLRequest.CachePolicy.reloadIgnoringLocalCacheData,
        timeoutInterval: 10 )

    let session = URLSession (
        configuration: URLSessionConfiguration.default,
        delegate: nil,
        delegateQueue: OperationQueue.main
    )

    let task = session.dataTask(with: request, completionHandler: { (data, response, error) in
        if let data = data {
            do { let shows = try! JSONDecoder().decode([Shows].self, from: data)
                self.shows = shows

            }
        }
    })

    task.resume()

}

How would I approach sorting through the array and finding each instance of name: being different, then take each name and place them into a new array?

JSharpp
  • 459
  • 1
  • 9
  • 21

1 Answers1

2

There are several ways to iterate through your array of Shows and their array of Theater to get the complete list of names. Once you have the full list of names you can get a unique list of those names.

Here is one approach:

let names = Array(Set(shows.map { $0.showtimes.map { $0.theatre.name }}.reduce([]) { $0 + $1 }))

Let's split that up to better explain what is going on.

let allNames = shows.map { $0.showtimes.map { $0.theatre.name }}.reduce([]) { $0 + $1 }
let uniqueNames = Array(Set(allNames))

The shows.map iterates through each Shows in shows. The inner map in turn iterates each Theatre in each of those Shows returning its name. So the inner map gives an array of names. The first map results in an array of arrays of names. The reduce merges those arrays of names into a single array of names leaving allNames with a single array containing every name.

The use of Array(Set(allNames)) first creates a unique set of the names and then it creates an array from that set.

If you want the final result to be sorted alphabetically then add .sorted() to the end.

If you need to keep the original order you can make use of NSOrderedSet and remove any use of sorted.

let names = NSOrderedSet(array: shows.map { $0.showtimes.map { $0.theatre.name }}.reduce([]) { $0 + $1 }).array as! [String]
rmaddy
  • 314,917
  • 42
  • 532
  • 579
  • This works but rather than sorting alphabetically. What would be the right method for them to be sorted in the order that they appear? Mine keep being sorted in random orders differently each time I run the app. – JSharpp Nov 11 '18 at 02:58
  • @JSharpp The use of `Set` causes the names to be out of order. See my updated answer using `NSOrderedSet` to keep the original order. – rmaddy Nov 11 '18 at 04:45
  • I get the error `Cast from 'NSOrderedSet' to unrelated type '[String] always fails` – JSharpp Nov 11 '18 at 16:33
  • Did you copy that line exactly as I have it? It works fine for me. Sounds like you missed the `.array` near the end. – rmaddy Nov 11 '18 at 16:40
  • That's what's missing. I created the array on a second line and did missed that part. – JSharpp Nov 11 '18 at 16:42
  • If I print it within the function it shows up properly but if I try and send it with `self.theaterNames = names` up to a var `var theaterNames = [String]()` outside of the function the var prints as an empty array. Do you know why it's not sending to the variable? – JSharpp Nov 11 '18 at 17:17
  • You are loading the data asynchronously. There are many existing questions on that topic. – rmaddy Nov 11 '18 at 17:18
  • Could you post a link to a relatable question? – JSharpp Nov 11 '18 at 17:27