Question or problem with Swift language programming:
lets say we have a custom class named imageFile and this class contains two properties.
class imageFile { var fileName = String() var fileID = Int() }
lots of them stored in Array
var images : Array = [] var aImage = imageFile() aImage.fileName = "image1.png" aImage.fileID = 101 images.append(aImage) aImage = imageFile() aImage.fileName = "image1.png" aImage.fileID = 202 images.append(aImage)
question is: how can i sort images array by ‘fileID’ ASC or DESC?
How to solve the problem:
Solution 1:
First, declare your Array as a typed array so that you can call methods when you iterate:
var images : [imageFile] = []
Then you can simply do:
Swift 2
images.sorted({ $0.fileID > $1.fileID })
Swift 3+
images.sorted(by: { $0.fileID > $1.fileID })
The example above gives desc sort order
Solution 2:
[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)
Solution 3:
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.
Solution 4:
Swift 3
people = people.sorted(by: { $0.email > $1.email })
Solution 5:
With Swift 5, Array
has two methods called sorted()
and sorted(by:)
. The first method, sorted()
, has the following declaration:
Returns the elements of the collection, sorted.
func sorted() -> [Element]
The second method, sorted(by:)
, has the following declaration:
Returns the elements of the collection, sorted using the given predicate as the comparison between elements.
func sorted(by areInIncreasingOrder: (Element, Element) throws -> Bool) rethrows -> [Element]
#1. Sort with ascending order for comparable objects
If the element type inside your collection conforms to Comparable
protocol, you will be able to use sorted()
in order to sort your elements with ascending order. The following Playground code shows how to use sorted()
:
class ImageFile: CustomStringConvertible, Comparable { let fileName: String let fileID: Int var description: String { return "ImageFile with ID: \(fileID)" } init(fileName: String, fileID: Int) { self.fileName = fileName self.fileID = fileID } static func ==(lhs: ImageFile, rhs: ImageFile) -> Bool { return lhs.fileID == rhs.fileID } static func <(lhs: ImageFile, rhs: ImageFile) -> Bool { return lhs.fileID < rhs.fileID } } let images = [ ImageFile(fileName: "Car", fileID: 300), ImageFile(fileName: "Boat", fileID: 100), ImageFile(fileName: "Plane", fileID: 200) ] let sortedImages = images.sorted() print(sortedImages) /* prints: [ImageFile with ID: 100, ImageFile with ID: 200, ImageFile with ID: 300] */
#2. Sort with descending order for comparable objects
If the element type inside your collection conforms to Comparable
protocol, you will have to use sorted(by:)
in order to sort your elements with a descending order.
class ImageFile: CustomStringConvertible, Comparable { let fileName: String let fileID: Int var description: String { return "ImageFile with ID: \(fileID)" } init(fileName: String, fileID: Int) { self.fileName = fileName self.fileID = fileID } static func ==(lhs: ImageFile, rhs: ImageFile) -> Bool { return lhs.fileID == rhs.fileID } static func <(lhs: ImageFile, rhs: ImageFile) -> Bool { return lhs.fileID < rhs.fileID } } let images = [ ImageFile(fileName: "Car", fileID: 300), ImageFile(fileName: "Boat", fileID: 100), ImageFile(fileName: "Plane", fileID: 200) ] let sortedImages = images.sorted(by: { (img0: ImageFile, img1: ImageFile) -> Bool in return img0 > img1 }) //let sortedImages = images.sorted(by: >) // also works //let sortedImages = images.sorted { $0 > $1 } // also works print(sortedImages) /* prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100] */
#3. Sort with ascending or descending order for non-comparable objects
If the element type inside your collection DOES NOT conform to Comparable
protocol, you will have to use sorted(by:)
in order to sort your elements with ascending or descending order.
class ImageFile: CustomStringConvertible { let fileName: String let fileID: Int var description: String { return "ImageFile with ID: \(fileID)" } init(fileName: String, fileID: Int) { self.fileName = fileName self.fileID = fileID } } let images = [ ImageFile(fileName: "Car", fileID: 300), ImageFile(fileName: "Boat", fileID: 100), ImageFile(fileName: "Plane", fileID: 200) ] let sortedImages = images.sorted(by: { (img0: ImageFile, img1: ImageFile) -> Bool in return img0.fileID < img1.fileID }) //let sortedImages = images.sorted { $0.fileID < $1.fileID } // also works print(sortedImages) /* prints: [ImageFile with ID: 300, ImageFile with ID: 200, ImageFile with ID: 100] */
Note that Swift also provides two methods called sort()
and sort(by:)
as counterparts of sorted()
and sorted(by:)
if you need to sort your collection in-place.