Sorting


Sorting things in swift

Regular sorting:

let eva = Human(firstName: "Eddie", lastName: "Van Halen" )
let jp = Human(firstName:"Jimmy", lastName: "Page")
let jh = Human(firstName:"Jimi", lastName: "Hendrix")
let sv = Human(firstName:"Steve", lastName: "Vai")
var guitarists = [eva, jp,jh, sv]

guitarists.sortInPlace({$0.firstName > $1.firstName})

for human in guitarists{
    Swift.print("human.firstName: " + "\(human.firstName)")
}

Custom sorting with a method:

import Cocoa


//((value1: String, value2: String) -> ())?
//Equatable
func conditionSort<T>(array:[T],_ condition: (a: T, b: T)->Bool)->Array<T>{
    var sortedArray:Array<T> = [];
    for (var i : Int = 0; i < array.count; i++) {
        let index:Int = Utils.index(array[i], sortedArray, condition);/**/
        if(index > -1){
            sortedArray = ArrayModifier.splice(&sortedArray,index, 1, [array[i],sortedArray[index]])
        }else{
            sortedArray.append(array[i]);/*add the weightedStyle to index 0 of the sortedStyles array or weigthedStyle does not have priority append weightedStyle to the end of the array */
        }
    }
    return sortedArray;
}

private class Utils{
    /**
     * Returns the index of the item in @param sortedArray that meets the @param condition method "true", if there is no item in the @param sortedArray meets the condition method "true" then return -1 (-1 means no match found)
     */
    class func index<T>(value:T, _ sortedArray:[T],_ condition:(a: T, b: T)->Bool)->Int{
        for (var i : Int = 0; i < sortedArray.count; i++) {
            if(condition(a: value,b: sortedArray[i])) {
                return i
            }
        }
        return -1;
    }
}
class ArrayModifier{
    class func splice<T>(inout array:[T],_ startIndex:Int,_ deleteCount:Int,_ values:Array<T> = [])->Array<T>{
        var returnArray = array
        returnArray.removeRange(Range<Int>(start:Int(startIndex),end:Int(startIndex + deleteCount)))
        if(values.count > 0 ){returnArray.insertContentsOf(values, at: Int(startIndex))}
        return returnArray
    }
}


//7,3,2,4,9,15,1
var numbers = [4,2,5,1,0,-1,22,3]

func before<T:Comparable>(a: T, b: T) -> Bool {
    return a < b;
}

let sortedNumbers = conditionSort(numbers, before)//-1,0,1,2,3,4,5,22
print(sortedNumbers)

class A:Comparable,CustomStringConvertible{
    var someNumber:Int
    var description: String { get{return String(someNumber)} }
    init(_ someNumber:Int){
        self.someNumber = someNumber
    }
}
func < (lhs: A, rhs: A) -> Bool {
    return lhs.someNumber < rhs.someNumber
}

func == (lhs: A, rhs: A) -> Bool {
    return lhs.someNumber == rhs.someNumber
}

var theList = [A(2),A(6),A(-4)]
print(conditionSort(theList, <))
//try a Custom class that is comparable

Custom sorting with Comparable and Equatable:

The Comparable protocol extends the Equatable protocol -> implement both of them

In Apple’s Reference is an example from Apple (within the Comparable protocol reference) you can see how you should do it: Don’t put the operation implementations within the class, but rather on the outside/global scope. Also you only have to implement the < operator.

Correct example:

class Person : Comparable {
    let name : String

    init(name : String) {
        self.name = name
    }
}

func < (lhs: Person, rhs: Person) -> Bool {
    return lhs.name < rhs.name
}

func == (lhs: Person, rhs: Person) -> Bool {
    return lhs.name == rhs.name
}

let paul = Person(name: "Paul")
let otherPaul = Person(name: "Paul")
let ben = Person(name: "Ben")

paul > otherPaul  // false
paul <= ben       // false
paul == otherPaul // true

EXAMPLE:

var numbers = [4,2,5,1,0,-1,22,3]

func before<T:Comparable>(a: T, b: T) -> Bool {
    return a < b;
}

let sortedNumbers = conditionSort(numbers, before)//-1,0,1,2,3,4,5,22
print(sortedNumbers)

NOTE: there is also: Striding over Strideable values, which are Comparable and can be advanced an arbitrary distance in O(1).