You don't need substringToIndex to get the first character of a Swift string. String is a CollectionType, to which this generic function from the standard library applies:
func first<C : CollectionType>(x: C) -> C.Generator.Element?
So you might start by trying something like this:
let imgRank = first(rankMap[rank]) ?? rank.description // error
That doesn't work, for two reasons:
String.Generator.Element is a Character, not a String, so if you're going to put it in a ?? expression, the right operand of ?? needs to also be a Character. You can construct a Character from a String (with Character(rank.description)), but that'll crash if that string has more than one character in it.
rankMap[rank] is an optional, so you can't pass it directly to first. But if you try to force-unwrap it immediately (with first(rankMap[rank]!), you'll crash upon looking up something not in the dictionary.
You could try solving these problems together by putting the ?? inside the first call, but you probably want a two-character string for rank 10.
It'd be nice if we could treat String like an Array, which provides var first for getting its first element. (And have a version of first for strings that returns a String.) Then we could take advantage of optional chaining to put a whole expression to the left of the ??, and just write:
let imgRank = rankMap[rank]?.first ?? rank.description
Well, let's write it in an extension!
extension String {
var first : String? {
// we're overloading the name of the global first() function,
// so access it with its module name
switch Swift.first(self) {
case let .Some(char):
return String(char)
case .None:
return nil
}
}
}
Now you can be nice and concise about it:
let imgRank = rankMap[rank]?.first ?? String(rank)
(Notice I'm also changing rank.description to String(rank). It's good to be clear -- description gives you a string representation of a value that's appropriate for printing in the debugger; String() converts a value to a string. The former is not guaranteed to always match the latter, so use the latter if that's what you really want.)
Anyhow, @RobNapier's advice stands: you're probably better off using enums for these. That gets you a lot less uncertainty about optionals and invalid lookups. But seeing what you can do with the standard library is always a useful exercise.
rankMap.