I want to extend Array class so that it can know whether it is sorted (ascending) or not. I want to add a computed property called isSorted
. How can I state the elements of the Array to be comparable?
My current implementation in Playground
extension Array { var isSorted: Bool { for i in 1..self.count { if self[i-1] > self[i] { return false } } return true } } // The way I want to get the computed property [1, 1, 2, 3, 4, 5, 6, 7, 8].isSorted //= true [2, 1, 3, 8, 5, 6, 7, 4, 8].isSorted //= false
The error Could not find an overload for '>' that accepts the supplied arguments
Of course, I still got an error because Swift doesn't know how to compare the elements. How can I implement this extension in Swift? Or am I doing something wrong here?
You don't need to sort your array to check if it's sorted. Loop over each consecutive pair of elements and check if the first is less than the second; if you find a pair for which this isn't true, the array is not sorted.
Any Swift Sequence (which includes common data structures, like arrays, dictionaries, and sets) can be sorted using the sorted API, which takes a closure that's used to determine the sort order by comparing two elements at a time. The built-in sorted method can be called on any Sequence (so not just arrays).
The basic idea for the recursive approach: 1: If size of array is zero or one, return true. 2: Check last two elements of array, if they are sorted, perform a recursive call with n-1 else, return false. If all the elements will be found sorted, n will eventually fall to one, satisfying Step 1.
Use the isEmpty property to check quickly whether an array has any elements, or use the count property to find the number of elements in the array.
The alternative solution to a free function is to do what Swift's built-in Array.sort
and Array.sorted
methods do, and require that you pass a suitable comparator to the method:
extension Array { func isSorted(isOrderedBefore: (T, T) -> Bool) -> Bool { for i in 1..<self.count { if !isOrderedBefore(self[i-1], self[i]) { return false } } return true } } [1, 5, 3].isSorted(<) // false [1, 5, 10].isSorted(<) // true [3.5, 2.1, -5.4].isSorted(>) // true
In Swift 2.0 you can now extend protocols!
extension CollectionType where Generator.Element: Comparable { public var isSorted: Bool { var previousIndex = startIndex var currentIndex = startIndex.successor() while currentIndex != endIndex { if self[previousIndex] > self[currentIndex] { return false } previousIndex = currentIndex currentIndex = currentIndex.successor() } return true } } [1, 2, 3, 4].isSorted // true ["a", "b", "c", "e"].isSorted // true ["b", "a", "c", "e"].isSorted // false [/* Anything not implementing `Comparable` */].isSorted // <~~ Type-error
Note that because we're using Indexable.Index
instead of a simple Int
as an index we have to use a while-loop instead, which looks a bit less pretty and clear.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With