Here is a Dictionary version of the answer from @vacawama. It is an alternative that might suit certain use cases better (or worse).
There are a few notable improvements in this version:
- Looking up a key in a dictionary is very fast O(1), where as using
find() on an array performs quite poorly as the list grows into the hundreds of cities O(N).
- Strings are allocated on the heap. This means the coordinate
struct as designed will behave similar to a class in terms of performance (slower). Your question did not present a strong case for storing the location name in the struct.
First create a struct to represent a coordinate.
struct Coordinate {
/// Latitude in decimal notation
let latitude: Double
/// Longitude in decimal notation
let longitude: Double
}
Then create the empty collection (per your question)
/// Empty mapping of location string to latitude-longitude
var coordinates = [String: Coordinate]()
Here’s an example of one way to populate the dictionary
/// Populate the locations
coordinates["New York, NY"] = Coordinate(latitude: 40.713054, longitude: -74.007228)
coordinates["Los Angeles, CA"] = Coordinate(latitude: 40.713054, longitude: -74.007228)
coordinates["Chicago, IL"] = Coordinate(latitude: 40.713054, longitude: -74.007228)
Example output:
print(coordinates["New York, NY"] ?? "Unknown Location”)
> "Coordinates(latitude: 40.713054, longitude: -74.007227999999998)”
That’s it!
A little further...
If the locations are known in advance, and if there are not hundreds of them, you might try using a string-backed enum
The above should answer the original question, however Swift allows even more interesting approaches using the type system.
We have guaranteed that a Coordinate is a pair of Double numbers, great! But, there are no guarantees about the integrity of a location. Later on you might accidentally type coordinates[“New york, NY”]. This will fail because “york” is lowercase! (and also in ever other answer currently posted). Here’s the enum:
enum Location: String {
case NY_NewYork = "New York, NY"
case CA_LosAngeles = "Los Angeles, CA"
case IL_Chicago = "Chicago, IL"
}
And change our dictionary key and usage accordingly
/// Empty mapping of location string to latitude-longitude
var coordinates = [Location: Coordinate]()
/// Populate the locations
coordinates[.NY_NewYork] = Coordinate(latitude: 40.713054, longitude: -74.007228)
coordinates[.CA_LosAngeles] = Coordinate(latitude: 40.713054, longitude: -74.007228)
coordinates[.IL_Chicago] = Coordinate(latitude: 40.713054, longitude: -74.007228)
We still have the original “New York, NY” title, but it is represented statically as the value Location.NY_NewYork. This means that the compiler will catch any mistakes that you might make!
One more thing: now that the location is a static constant value, we can actually put it back inside the struct without incurring a dreaded heap allocation! (The struct value will be a reference to the enumerated value).
Here’s the final version:
enum Location: String {
case NY_NewYork = "New York, NY"
case CA_LosAngeles = "Los Angeles, CA"
case IL_Chicago = "Chicago, IL"
}
struct Coordinate {
/// The logical name of the location referenced by this coordinate
let location: Location
/// Latitude in decimal notation
let latitude: Double
/// Longitude in decimal notation
let longitude: Double
}
/// Empty mapping of location string to latitude-longitude
var coordinates = [Location: Coordinate]()
/// Populate the locations
coordinates[.NY_NewYork] = Coordinate(location: .NY_NewYork, latitude: 40.713054, longitude: -74.007228)
coordinates[.CA_LosAngeles] = Coordinate(location: .CA_LosAngeles, latitude: 40.713054, longitude: -74.007228)
coordinates[.IL_Chicago] = Coordinate(location: .IL_Chicago, latitude: 40.713054, longitude: -74.007228)
// or if initializing from a data source, something like...
// if let loc = Location(rawValue: "Chicago, IL") {
// coordinates[loc] = Coordinate(location: loc, latitude: 40.713054, longitude: -74.007228)
// }
And the output
print(coordinates[Location.NY_NewYork] ?? "uknown”)
> "Coordinate(location: Location.NY_NewYork, latitude: 40.713054, longitude: -74.007227999999998)”
Cool! Now we have perfect type-safety, the convenience of keeping the location title in there, and a very high-performance architecture.
This is what makes Swift a special tool for iOS.
locationsin the Xcode source editor and you'll see the type. (But then follow Hamish's suggestion.)