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 Object
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()