Q:

Working in swift with tuples - sorting and reporting range of values for each key

I'm trying to pull a range of values from an array of tuples for each unique value.  Ultimately the source data is JSON and I'm pulling the various locations and matching times for appointment data and placing it in a tuple for temporary storage and data manipulation (maybe I'm making this more complex than it needs to be).
My array is a location and a time such as this:
var tuple_array = [("Clinic", "1200"), ("ASC", "0900"), ("Clinic", "1300"), ("ASC", "0830"), ("Clinic", "1400")]

I'd ultimately like a report that says "You have 2 appointments at "ASC" from 0830-0900 and 3 appointments at "Clinic" from 1200-1400."
So far, I've been able to pull out the number of unique entries for each location and can sort the array based on time, but I haven't been able to figure out how to report on the ranges.  
To pull the unique values I ran:
let test = tuple_array.map { $0.0 }
let uniqueValues = test.reduce([], { $0.contains($1) ? $0 : $0 + [$1] })

I'm also able to sort the array of tuples to see the range of times for the day (first and last entry in the array):
future_appts_counts_location_time_array.sort {$0.1 == $1.1 ? $0.1 < $1.1 : $0.1 < $1.1 }

but I'm struggling to see how to get separate ranges for each location based on this.  
Any advice?
Thanks!

A:

There's a Dictionary constructor that will really help you out:
let placeTimes = Dictionary(grouping: tuple_array, by: { $0.0 })
    .mapValues { $0.map { $0.1 }.sorted() }

The constructor will produce a dictionary where the keys are the places and the values are the tuples. The mapValues will take the array of tuples, slice off the first part and then sort the last part.
The above doesn't guarantee that the places will be in alphabetical order. If you need that you can tack on .sorted(by: { $0.0 < $1.0 }) after the mapValues command.
let descriptions = placeTimes.map { arg -> String in
    let (key, value) = arg
    switch value.count {
    case 0:
        return "no appointments at \"\(key)\""
    case 1:
        return "1 appointment at \"\(key)\" at \(value.first!)"
    default:
        return "\(value.count) appointments at \"\(key)\" from \(value.first!)-\(value.last!)"
    }
    }
    .joined(separator: " and ")
print("You have \(descriptions)")

The above is one way of writing your complete sentence. The separator isn't very complex and won't work for English if there are more than two places (and if you have to internationalize this code it gets even more complex.)

