If will be easier if you convert myCustomString
into an array of characters. Working with Swift's String
is a bit of a pain the neck since the subscripting API is so clumsy. Here's one way to do it:
Swift 3:
var myArray = ["Dog", "B-1", "C-1", "C-2", "C-3","Home"]
let myCustomString = "DC".characters.map { $0 }
myArray.sort { str1, str2 in
let index1 = str1.isEmpty ? nil : myCustomString.index(of: str1[str1.startIndex])
let index2 = str2.isEmpty ? nil : myCustomString.index(of: str2[str2.startIndex])
switch (index1, index2) {
case (nil, nil):
return str1.compare(str2, options: .numeric) == .orderedAscending
case (nil, _):
return false
case (_, nil):
return true
default:
if index1 != index2 {
return index1! < index2!
} else {
return str1.compare(str2, options: .numeric) == .orderedAscending
}
}
}
print(myArray)
Original answer:
- Split
myArray
into 2 subarrays: one containing all the elements you have an order for; and one for elements that you do not
- Sort
subArray1
according to the order you specified
- Sort
subarray2
alphabetically
- Concatenate
subArray1
and subArray2
to make the new myArray
Example:
let myOrder = "DC".characters.map { $0 }
var myArray = ["Dog", "B-1", "C-1", "C-2", "C-3", "Home"]
var subArray1 = [String]()
var subArray2 = [String]()
myArray.forEach {
if $0.isEmpty || !myOrder.contains($0[$0.startIndex]) {
subArray2.append($0)
} else {
subArray1.append($0)
}
}
subArray1.sort { str1, str2 in
let firstChar1 = str1[str1.startIndex]
let firstChar2 = str2[str2.startIndex]
let index1 = myOrder.index(of: firstChar1)!
let index2 = myOrder.index(of: firstChar2)!
if index1 != index2 {
return index1 < index2
} else {
return str1.compare(str2, options: .numeric) == .orderedAscending
}
}
subArray2.sort { $0.compare($1, options: .numeric) == .orderedAscending }
myArray = subArray1 + subArray2
print(myArray)