11

In my code, I have a struct like the following:

struct Object {
 var name: String
 var count: Int

I am now creating an array of 10 Objects with random names and random counts.

Is there an easy way to
a) sort them alphabetically
b) sort them numerically in ascending order

Basically, there will be an array like so: [Object1, Object2, Object3]. Every Object has a name and count attribute, and I want the objects in that list be sorted via these two attributes.

Solution in Swift2 (using this solution: StackOverflow):

Object.sort{
 if 0ドル.name != 1ドル.name {
 return 0ドル.name < 1ドル.name
 }
 else {
 //suits are the same
 return 0ドル.count < 1ドル.count
 }
 }

However, this has been renamed to sorted(by: ) in Swift3, and I don't quit get how to do that.

asked Jan 14, 2017 at 8:37
5
  • 2
    developer.apple.com/reference/swift/array/2296801-sort Commented Jan 14, 2017 at 8:42
  • While this link has provided me with some explanation, I still have no clue how to do this with elements. Also, in none of the example things are sorted by 2 criteria, e.g. first name & last name Commented Jan 14, 2017 at 8:56
  • Possible duplicate of Swift - Sort array of objects with multiple criteria Commented Jan 14, 2017 at 9:12
  • In order to preserve the Stack Overflow Q&A format, in the future I'd suggest you do not edit your question to repeat the answer shown below (or found elsewhere). And if you really felt compelled to provide your own answer, then post it as an answer, below, rather than editing your question to include it there. Commented Jan 14, 2017 at 9:43
  • 1
    I will keep that in mind for the future! Commented Jan 14, 2017 at 9:45

3 Answers 3

28

If you want to sort alphabetically and then numerically, you can:

var array = ["A2", "B7", "A4", "C3", "A1", "A10"]
array.sort { 0ドル.compare(1,ドル options: .numeric) == .orderedAscending }

That produces:

["A1", "A2", "A4", "A10", "B7", "C3"]

I added A10 to your array, because without it, a simple alphabetic sort would have been sufficient. But I'm assuming you wanted A10 after A4, in which case the numeric comparison will do the job for you.


You changed the example to be a struct with two properties. In that case, you can do something like:

struct Foo {
 var name: String
 var count: Int
}
var array = [
 Foo(name:"A", count: 2),
 Foo(name:"B", count: 7),
 Foo(name:"A", count: 7),
 Foo(name:"C", count: 3),
 Foo(name:"A", count: 1),
 Foo(name:"A", count: 10)
]
array.sort { (object1, object2) -> Bool in
 if object1.name == object2.name {
 return object1.count < object2.count
 } else {
 return object1.name < object2.name
 }
}

Or, more concisely:

array.sort { 0ドル.name == 1ドル.name ? 0ドル.count < 1ドル.count : 0ドル.name < 1ドル.name }

Or

array.sort { (0ドル.name, 0ドル.count) < (1ドル.name, 1ドル.count) }

Note, rather than putting this logic in the closure, I'd actually make Foo conform to Comparable:

struct Foo {
 var name: String
 var count: Int
}
extension Foo: Equatable {
 static func ==(lhs: Foo, rhs: Foo) -> Bool {
 return (lhs.name, lhs.count) == (rhs.name, rhs.count)
 }
}
extension Foo: Comparable {
 static func <(lhs: Foo, rhs: Foo) -> Bool {
 return (lhs.name, lhs.count) < (rhs.name, rhs.count)
 }
}

This keeps the comparison logic nicely encapsulated within the Foo type, where it belongs.

Then you can just do the following to sort in place:

var array = ...
array.sort()

Or, alternatively, you can return a new array if you don't want to sort the original one in place:

let array = ...
let sortedArray = array.sorted()
answered Jan 14, 2017 at 9:16
7
  • 1
    No, in Swift 3, sorted is the version that returns a new array. sort is the version that sorts in place. Commented Jan 14, 2017 at 9:34
  • 1
    Then you must not be sorting in place, but rather trying to return it as a new array, in which case you'd do let sortedArray = array.sorted() { ... }. Commented Jan 14, 2017 at 9:38
  • Sorry that I can't do anything more than up vote your answer and comments, you deserve way more! Commented Jan 14, 2017 at 9:39
  • why did you write static func? Commented Jan 14, 2017 at 12:33
  • 1
    In Swift 2, the equality and comparison operators were implemented as globals, but in Swift 3 they are defined as static methods of the type, which keeps your code a little better organized. See Improving operators in protocols. Commented Jan 14, 2017 at 16:35
11

Narusan, maybe this will help you. Let's say you have an array with your struct objects called objArray, then you can order it by the code bellow:

var objArray = [Object]()
objArray.append(Object(name:"Steve", count:0))
objArray.append(Object(name:"Alex", count:1))
objNameSorted = objArray.sorted (by: {0ドル.name < 1ドル.name})
objNCountSorted = objArray.sorted (by: {0ドル.count < 1ドル.count})
answered Apr 20, 2017 at 7:13
1
  • You can still use shorthand for sorted: objNameSorted = objArray.sorted { 0ドル < 1ドル } While less readable, it more closely mimics the sort syntax. Commented Jun 8, 2017 at 11:57
7

You can still use shorthand for sorted:

objNameSorted = objArray.sorted { 0ドル < 1ドル }

While less readable, it more closely mimics the sort syntax.

answered Jun 8, 2017 at 11:58

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.