Before you write the implementation code for something like this, I suggest starting with a test.
To aid my thinking, I would make a table, with one column for every "attribute", and one for the result. In this case, the attributes being compared are length and lexicographic (alphabetic) ordering.
The precise values (lengths, string values, etc.) don't matter, only their relative values.
| Length | Lexicographic Ordering | s1 comes before s2? | Reason |
|----------------------|------------------------|---------------------|----------------------------------------------------|
| s1.count < s2.count | s1 < s2 | true | s1 is shorter |
| s1.count < s2.count | s1 == s2 | | Not possible |
| s1.count < s2.count | s1 > s2 | | Not possible |
| s1.count == s2.count | s1 < s2 | true | Length is same, but s1 is first alphabetically |
| s1.count == s2.count | s1 == s2 | false | They're the same string, neither is first |
| s1.count == s2.count | s1 > s2 | false | Length is same, but s2 is first alphabetically |
| s1.count > s2.count | s1 < s2 | false | Not possible |
| s1.count > s2.count | s1 == s2 | | Not possible |
| s1.count > s2.count | s1 > s2 | false | s2 is shorter |
From there, you can make some sample inputs that can reproduce each of these cases:
| Case | s1 | s2 | Length | Lexicographic Ordering | s1 comes before s2? | Reason |
|------|-------|-------|----------------------|------------------------|---------------------|----------------------------------------------------|
| 1 | "*" | "***" | s1.count < s2.count | s1 < s2 | true | s1 is shorter |
| | | | s1.count < s2.count | s1 == s2 | | Not possible |
| | | | s1.count < s2.count | s1 > s2 | | Not possible |
| 2 | "a" | "z" | s1.count == s2.count | s1 < s2 | true | Length is same, but s1 is first alphabetically |
| 3 | "foo" | "foo" | s1.count == s2.count | s1 == s2 | false | They're the same string, neither is first |
| 4 | "z" | "a" | s1.count == s2.count | s1 > s2 | false | Length is same, but s2 is first alphabetically |
| | | | s1.count > s2.count | s1 < s2 | false | Not possible |
| | | | s1.count > s2.count | s1 == s2 | | Not possible |
| 5 | "***" | "*" | s1.count > s2.count | s1 > s2 | false | s2 is shorter |
You can use this table to then create some test cases:
func sorter(_ s1: String, _ s2: String) -> Bool {
fatalError("implement me")
}
final class SorterTests: XCTestCase {
func testShorterStringsComeFirst() {
let short = "*"
let long = "***"
let case1 = sorter(short, long)
XCTAssertEqual(true, case1)
let case6 = sorter(long, short)
XCTAssertEqual(false, case6)
}
func testEqualLengthStringsAreLexicographicallySorted() {
let earlier = "a"
let later = "z"
let case2 = sorter(earlier, later)
XCTAssertEqual(true, case2)
let case4 = sorter(later, earlier)
XCTAssertEqual(false, case4)
}
func testEqualStringsArentBeforeThemselves() {
let anyString = "foo"
let case5 = sorter(anyString, anyString)
XCTAssertEqual(false, case5)
}
}
You can then use these tests to guide the creation of your sorting closure.