lets say we have a custom class named imageFile and this class contains two properties.
class imageFile {
var fileName = String()
var fileID = Int(
you can sort by KeyPath
like this:
myArray.sorted(by: \.fileName, <) /* using `<` for ascending sorting */
By implementing this little helpful extension.
extension Collection{
func sorted<Value: Comparable>(
by keyPath: KeyPath<Element, Value>,
_ comparator: (_ lhs: Value, _ rhs: Value) -> Bool) -> [Element] {
sorted { comparator($0[keyPath: keyPath], $1[keyPath: keyPath]) }
}
}
Hope Swift add this in the near future in the core of the language.
Nearly everyone gives how directly, let me show the evolvement:
you can use the instance methods of Array:
// general form of closure
images.sortInPlace({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
// types of closure's parameters and return value can be inferred by Swift, so they are omitted along with the return arrow (->)
images.sortInPlace({ image1, image2 in return image1.fileID > image2.fileID })
// Single-expression closures can implicitly return the result of their single expression by omitting the "return" keyword
images.sortInPlace({ image1, image2 in image1.fileID > image2.fileID })
// closure's argument list along with "in" keyword can be omitted, $0, $1, $2, and so on are used to refer the closure's first, second, third arguments and so on
images.sortInPlace({ $0.fileID > $1.fileID })
// the simplification of the closure is the same
images = images.sort({ (image1: imageFile, image2: imageFile) -> Bool in return image1.fileID > image2.fileID })
images = images.sort({ image1, image2 in return image1.fileID > image2.fileID })
images = images.sort({ image1, image2 in image1.fileID > image2.fileID })
images = images.sort({ $0.fileID > $1.fileID })
For elaborate explanation about the working principle of sort, see The Sorted Function.
var students = ["Kofi", "Abena", "Peter", "Kweku", "Akosua"]
students.sort(by: >)
print(students)
Prints : "["Peter", "Kweku", "Kofi", "Akosua", "Abena"]"
[Updated for Swift 3 with sort(by:)] This, exploiting a trailing closure:
images.sorted { $0.fileID < $1.fileID }
where you use <
or >
depending on ASC or DESC, respectively. If you want to modify the images
array, then use the following:
images.sort { $0.fileID < $1.fileID }
If you are going to do this repeatedly and prefer to define a function, one way is:
func sorterForFileIDASC(this:imageFile, that:imageFile) -> Bool {
return this.fileID > that.fileID
}
and then use as:
images.sort(by: sorterForFileIDASC)
If you are going to be sorting this array in more than one place, it may make sense to make your array type Comparable.
class MyImageType: Comparable, Printable {
var fileID: Int
// For Printable
var description: String {
get {
return "ID: \(fileID)"
}
}
init(fileID: Int) {
self.fileID = fileID
}
}
// For Comparable
func <(left: MyImageType, right: MyImageType) -> Bool {
return left.fileID < right.fileID
}
// For Comparable
func ==(left: MyImageType, right: MyImageType) -> Bool {
return left.fileID == right.fileID
}
let one = MyImageType(fileID: 1)
let two = MyImageType(fileID: 2)
let twoA = MyImageType(fileID: 2)
let three = MyImageType(fileID: 3)
let a1 = [one, three, two]
// return a sorted array
println(sorted(a1)) // "[ID: 1, ID: 2, ID: 3]"
var a2 = [two, one, twoA, three]
// sort the array 'in place'
sort(&a2)
println(a2) // "[ID: 1, ID: 2, ID: 2, ID: 3]"
I do it like this and it works:
var images = [imageFile]()
images.sorted(by: {$0.fileID.compare($1.fileID) == .orderedAscending })