178

I have this:

class Movies {
 Name:String
 Date:Int
}

and an array of [Movies]. How do I sort the array alphabetically by name? I've tried:

movieArr = movieArr.sorted{ 0ドル < 1ドル }

and

movieArr = sorted(movieArr)

but that doesn't work because I'm not accessing the name attribute of Movies.

Sahil Kapoor
11.8k13 gold badges69 silver badges92 bronze badges
asked Nov 3, 2014 at 17:36

7 Answers 7

392

In the closure you pass to sort, compare the properties you want to sort by. Like this:

movieArr.sorted { 0ドル.name < 1ドル.name }

or the following in the cases that you want to bypass cases:

movieArr.sorted { 0ドル.name.lowercased() < 1ドル.name.lowercased() }

Sidenote: Typically only types start with an uppercase letter; I'd recommend using name and date, not Name and Date.


Example, in a playground:

class Movie {
 let name: String
 var date: Int?
 
 init(_ name: String) {
 self.name = name
 }
}
var movieA = Movie("A")
var movieB = Movie("B")
var movieC = Movie("C")
let movies = [movieB, movieC, movieA]
let sortedMovies = movies.sorted { 0ドル.name < 1ドル.name }
sortedMovies

sortedMovies will be in the order [movieA, movieB, movieC]

Swift5 Update

channelsArray = channelsArray.sorted { (channel1, channel2) -> Bool in
 let channelName1 = channel1.name
 let channelName2 = channel2.name
 return (channelName1.localizedCaseInsensitiveCompare(channelName2) == .orderedAscending)
}
Joannes
2,9684 gold badges20 silver badges42 bronze badges
answered Nov 3, 2014 at 17:41
7
  • 1
    use movies.sort instead of movies.sorted @Mike S Commented Nov 4, 2015 at 11:22
  • @julian-król You forgot to edit the other sorted to sort in the answer. Note: this is not a typo, sorted was correct in Swift 1 but has become sort in Swift 2. Commented Dec 3, 2015 at 10:47
  • 1
    thanks for explanation. Improved my edit, should be fine, please take a look :) Commented Dec 3, 2015 at 10:56
  • 12
    Beware, this won't work when sorting string that may or may not be capitalized. Comparing the .lowercaseString will solve this problem. Commented Feb 26, 2016 at 14:41
  • 2
    @EricAya Note it is sorted in Swift 3 again :D . Commented Dec 9, 2016 at 15:44
57

With Swift 3, you can choose one of the following ways to solve your problem.


1. Using sorted(by:​) with a Movie class that does not conform to Comparable protocol

If your Movie class does not conform to Comparable protocol, you must specify in your closure the property on which you wish to use Array's sorted(by:​) method.

Movie class declaration:

import Foundation
class Movie: CustomStringConvertible {
 let name: String
 var date: Date
 var description: String { return name }
 init(name: String, date: Date = Date()) {
 self.name = name
 self.date = date
 }
}

Usage:

let avatarMovie = Movie(name: "Avatar")
let titanicMovie = Movie(name: "Titanic")
let piranhaMovie = Movie(name: "Piranha II: The Spawning")
let movies = [avatarMovie, titanicMovie, piranhaMovie]
let sortedMovies = movies.sorted(by: { 0ドル.name < 1ドル.name })
// let sortedMovies = movies.sorted { 0ドル.name < 1ドル.name } // also works
print(sortedMovies)
/*
prints: [Avatar, Piranha II: The Spawning, Titanic]
*/

2. Using sorted(by:​) with a Movie class that conforms to Comparable protocol

However, by making your Movie class conform to Comparable protocol, you can have a much concise code when you want to use Array's sorted(by:​) method.

Movie class declaration:

import Foundation
class Movie: CustomStringConvertible, Comparable {
 let name: String
 var date: Date
 var description: String { return name }
 init(name: String, date: Date = Date()) {
 self.name = name
 self.date = date
 }
 static func ==(lhs: Movie, rhs: Movie) -> Bool {
 return lhs.name == rhs.name
 }
 static func <(lhs: Movie, rhs: Movie) -> Bool {
 return lhs.name < rhs.name
 }
}

Usage:

let avatarMovie = Movie(name: "Avatar")
let titanicMovie = Movie(name: "Titanic")
let piranhaMovie = Movie(name: "Piranha II: The Spawning")
let movies = [avatarMovie, titanicMovie, piranhaMovie]
let sortedMovies = movies.sorted(by: { 0ドル < 1ドル })
// let sortedMovies = movies.sorted { 0ドル < 1ドル } // also works
// let sortedMovies = movies.sorted(by: <) // also works
print(sortedMovies)
/*
 prints: [Avatar, Piranha II: The Spawning, Titanic]
 */

3. Using sorted() with a Movie class that conforms to Comparable protocol

By making your Movie class conform to Comparable protocol, you can use Array's sorted() method as an alternative to sorted(by:​).

Movie class declaration:

import Foundation
class Movie: CustomStringConvertible, Comparable {
 let name: String
 var date: Date
 var description: String { return name }
 init(name: String, date: Date = Date()) {
 self.name = name
 self.date = date
 }
 static func ==(lhs: Movie, rhs: Movie) -> Bool {
 return lhs.name == rhs.name
 }
 static func <(lhs: Movie, rhs: Movie) -> Bool {
 return lhs.name < rhs.name
 }
}

Usage:

let avatarMovie = Movie(name: "Avatar")
let titanicMovie = Movie(name: "Titanic")
let piranhaMovie = Movie(name: "Piranha II: The Spawning")
let movies = [avatarMovie, titanicMovie, piranhaMovie]
let sortedMovies = movies.sorted()
print(sortedMovies)
/*
 prints: [Avatar, Piranha II: The Spawning, Titanic]
 */
answered Dec 19, 2015 at 11:45
6
  • Hey, Is there any diff. between 2nd and 3rd (except movies.sorted(by: <) and movies.sorted()) ? Commented Dec 15, 2017 at 11:10
  • sorted(by:) and sorted() are two different methods. You can use array.sorted() as an alternative for array.sorted(by: <). Commented Dec 15, 2017 at 11:17
  • Yes, just asking in case of class definition do we need to change anything? I mean, can we have same class definition for both sorted(by:) and sorted() ? Commented Dec 15, 2017 at 11:26
  • 1
    Yes, you can have the same implementation of your class/struct that, in any case, has to conform to Comparable protocol. Commented Dec 15, 2017 at 16:02
  • I have Array with customObject when i shoer in ascending order it's not shorting in proper way. "1" "14""28""31""4""42""49" Commented Aug 17, 2019 at 10:53
21
let sortArray = array.sorted(by: { 0ドル.name.lowercased() < 1ドル.name.lowercased() })
Maak
5,0873 gold badges30 silver badges39 bronze badges
answered Mar 28, 2018 at 14:14
2
  • adding .lowercased() worked for me after a long period of trying. I don't understand why, since all text were lowercased to begin with. Commented Dec 17, 2018 at 18:59
  • when use lowercased() will change all names to lower case to sorted properly :) Commented Dec 18, 2018 at 7:26
14

For those using Swift 3, the equivalent method for the accepted answer is:

movieArr.sorted { 0ドル.Name < 1ドル.Name }
answered Feb 5, 2017 at 20:55
3

Most of these answers are wrong due to the failure to use a locale based comparison for sorting. Look at localizedStandardCompare()

answered Sep 18, 2020 at 22:55
0
1

Sorted array Swift 4.2

arrayOfRaces = arrayOfItems.sorted(by: { (0ドル["raceName"] as! String) < (1ドル["raceName"] as! String) })
answered Apr 25, 2019 at 13:05
0
*import Foundation
import CoreData
extension Messages {
 @nonobjc public class func fetchRequest() -> NSFetchRequest<Messages> {
 return NSFetchRequest<Messages>(entityName: "Messages")
 }
 @NSManaged public var text: String?
 @NSManaged public var date: Date?
 @NSManaged public var friends: Friends?
}
 //here arrMessage is the array you can sort this array as under bellow 
 var arrMessages = [Messages]()
 arrMessages.sort { (arrMessages1, arrMessages2) -> Bool in
 arrMessages1.date! > arrMessages2.date!
 }*
answered Mar 5, 2020 at 21:21

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.