Reputation: 2733
I've got the below struct
and would like to sort the items within sessions by startTime
field. I'm completely lost on how to do this.
I tried:
let sortedArray = sessionsData?.items.sorted{ ($0["startTime"] as! String) < ($1["startTime"] as! String) }
but that just gives me an error about no subscript members?
Any pointers would really be appreciated, thank you.
public struct sessions: Decodable {
let status: String?
let start: Int?
let count: Int?
let items: [sessionInfo]?
let itemsCount: Int?
let multipart: Bool?
let startTime: Int?
let endTime: Int?
}
public struct sessionInfo: Decodable {
let name: String?
let datalist: String?
let sessionType: Int?
let status: Int?
let backupType: Int?
let startTime: Int?
let endTime: Int?
let owner: String?
let numOfErrors: Int?
let numOfWarnings: Int?
let flags: Int?
}
I tried the below, but get an error:
var sortedArray = sessionsData?.items?.sorted(by: { (lhs, rhs) -> Bool in
return lhs.startTime < rhs.startTime
})
error:
Binary operator '<' cannot be applied to two 'Int?' operands
Upvotes: 3
Views: 3798
Reputation: 923
You have default High Order Function
for sorting the struct array in ascending and descending order
Example
let roster: [TeamMember] = [.init(id: 1, name: "Abishek", age: 19),
.init(id: 2, name: "Dinesh", age: 22),
.init(id: 3, name: "Praveen", age: 24),
.init(id: 4, name: "Sam", age: 25),
.init(id: 5, name: "David", age: 21)]
let descendingSorted = roster.sorted{$0.name > $1.name} // for descending order
let ascendingSorted = roster.sorted{$0.name < $1.name} // for ascending order
print(descendingSorted)
print(ascendingSorted)
Your Output
// for descending order
[TeamMember(id: 4, name: "Sam", age: 25.0),
TeamMember(id: 3, name: "Praveen", age: 24.0),
TeamMember(id: 2, name: "Dinesh", age: 22.0),
TeamMember(id: 5, name: "David", age: 21.0),
TeamMember(id: 1, name: "Abishek", age: 19.0)]
// for ascending order
[TeamMember(id: 1, name: "Abishek", age: 19.0),
TeamMember(id: 5, name: "David", age: 21.0),
TeamMember(id: 2, name: "Dinesh", age: 22.0),
TeamMember(id: 3, name: "Praveen", age: 24.0),
TeamMember(id: 4, name: "Sam", age: 25.0)]
And we have another one method for sorting is SortComparator
. we sort the result based on ComparisonResult
let descendingSorted1 = roster.sorted { teamMember1, teamMember2 in
return teamMember1.name.compare(teamMember2.name) == .orderedDescending
} // for descending order
let ascendingSorted1 = roster.sorted{ teamMember1, teamMember2 in
return teamMember1.name.compare(teamMember2.name) == .orderedAscending
} // for ascending order
print(descendingSorted1)
print(ascendingSorted1)
Upvotes: 0
Reputation: 1385
Try below code, it sorts the struct in asc order but it pushes nil timestamps to bottom. if you want nil timestamps to be at top, make all nil checks in below code to return opposite of what i return in below code.
var sortedArray = sessionsData?.items?.sorted(by: { (lhs, rhs) -> Bool in
if let lhsTime = lhs.startTime, let rhsTime = rhs.startTime {
return lhs.startTime < rhs.startTime
}
if lhs.startTime == nil && rhs.startTime == nil {
// return true to stay at top
return false
}
if lhs.startTime == nil {
// return true to stay at top
return false
}
if rhs.startTime == nil {
// return false to stay at top
return true
}
})
Upvotes: 4
Reputation: 884
You could write this (tested in playground) :
var sortedArray = sessionsData?.items?.sorted(by: { (lhs, rhs) -> Bool in return (lhs.startTime ?? 0) < (rhs.startTime ?? 0) })
If one is optional, you do not crash, even though result of comparison is meaningless
Upvotes: 1
Reputation: 12109
You should access the fields directly and not through subscripts.
let sortedArray = sessionsData?.items.sorted(by: {$0.startTime < $1.startTime})
Upvotes: 2