Reputation: 8896
I have an array of a custom class
class GameInfo {
var gameStatus :String
var country : String
var isSelected : Bool
}
Here, gameStatus
may be "*"/"1-0"/"1/2-1/2"
I want to sort the array first by isSelected
, then gameStatus
, then country
.
I tried sortInPlace
but didn't work for me.
suppose this is my array
let list = [
GameInfo(gameStatus: "*", country: "Italy", isSelected: true),
GameInfo(gameStatus: "1/2-1/2", country: "France", isSelected: true),
GameInfo(gameStatus: "1-0", country: "Italy", isSelected: false),
GameInfo(gameStatus: "*", country: "Germany", isSelected: false),
GameInfo(gameStatus: "0-1", country: "Italy", isSelected: true),
GameInfo(gameStatus: "1/2-1/2", country: "France", isSelected: false),
GameInfo(gameStatus: "*", country: "UK", isSelected: false)
]
Selected games should be on top if with in selected game there is any live game that game should be on top even with in any game related to my country that game on top
suppose my country is Italy then sorted order of array is
GameInfo(gameStatus: "*", country: "Italy", isSelected: true),
GameInfo(gameStatus: "0-1", country: "Italy", isSelected: true),
GameInfo(gameStatus: "1/2-1/2", country: "France", isSelected: true),
GameInfo(gameStatus: "*", country: "Germany", isSelected: false),
GameInfo(gameStatus: "*", country: "UK", isSelected: false)
GameInfo(gameStatus: "1-0", country: "Italy", isSelected: false),
GameInfo(gameStatus: "1/2-1/2", country: "France", isSelected: false),
Upvotes: 0
Views: 650
Reputation: 4329
Try this.
your class look like below
import UIKit
class GameInfo : NSObject {
var gameStatus :String = ""
var country : String = ""
var isSelected : Bool = false
init(gameStatus: String, country: String, isSelected: Bool) {
self.gameStatus = gameStatus
self.country = country
self.isSelected = isSelected
}
}
And use this code for sorting. As per your need, you can set ascending parameter.
let list :NSArray = [
GameInfo(gameStatus: "*", country: "Italy", isSelected: true),
GameInfo(gameStatus: "1/2/21", country: "France", isSelected: true),
GameInfo(gameStatus: "1-0", country: "UK", isSelected: true),
GameInfo(gameStatus: "*", country: "Germany", isSelected: false),
GameInfo(gameStatus: "0-1", country: "Italy", isSelected: true),
GameInfo(gameStatus: "1/2-1/2", country: "UK", isSelected: false)
]
let isSelectedDescriptor: NSSortDescriptor = NSSortDescriptor(key: "isSelected", ascending: false)
let gameStatusDescriptor: NSSortDescriptor = NSSortDescriptor(key: "gameStatus", ascending: true)
let countryDescriptor: NSSortDescriptor = NSSortDescriptor(key: "country", ascending: true)
let sortedResults: NSArray = list.sortedArrayUsingDescriptors([isSelectedDescriptor,gameStatusDescriptor,countryDescriptor])
dump(sortedResults)
Upvotes: -1
Reputation: 15784
try this (old style Objective-C array sorting):
let sortedArray = (yourArray as NSArray).sortedArrayUsingDescriptors([
NSSortDescriptor(key: "isSelected", ascending: true),
NSSortDescriptor(key: "gameStatus", ascending: true),
NSSortDescriptor(key: "country", ascending: true)
]) as! [GameInfo]
In that case, your GameInfo class must be like this. It's not the easy way to resolve your problem, just for info. Sorting with multiple conditions is very easy and natural with NSSortDescriptors but for Objective-C only, unless our swift classes are under some conditions (implementations).
class GameInfo : NSObject {
var gameStatus: String?
var country: String?
var isSelected: Bool
init(gameStatus: String, country: String, isSelected: Bool) {
self.gameStatus = gameStatus
self.country = country
self.isSelected = isSelected
}
override func valueForKey(key: String) -> AnyObject? {
if (key == "gameStatus") {
return self.gameStatus
} else if (key == "country") {
return self.country
} else if (key == "isSelected") {
return self.isSelected
} else {
return nil
}
}
}
Upvotes: 1
Reputation: 59496
You can write your own logic into the closure you pass to sort
.
So given this class
class GameInfo {
var gameStatus: String
var country: String
var isSelected: Bool
init(gameStatus: String, country: String, isSelected: Bool) {
self.gameStatus = gameStatus
self.country = country
self.isSelected = isSelected
}
}
and this list
let list = [
GameInfo(gameStatus: "A", country: "Italy", isSelected: true),
GameInfo(gameStatus: "A", country: "France", isSelected: true),
GameInfo(gameStatus: "B", country: "UK", isSelected: true),
GameInfo(gameStatus: "B", country: "Germany", isSelected: false),
GameInfo(gameStatus: "A", country: "Italy", isSelected: true),
GameInfo(gameStatus: "B", country: "UK", isSelected: false)
]
you can created a sorted list this way
let sorted = list.sort {
guard $0.isSelected == $1.isSelected else { return $0.isSelected }
guard $0.gameStatus == $1.gameStatus else { return $0.gameStatus < $1.gameStatus }
guard $0.country == $1.country else { return $0.country < $1.country }
return true
}
You can make your GameInfo
class conform to Comparable
.
class GameInfo: Comparable {
var gameStatus: String
var country: String
var isSelected: Bool
init(gameStatus: String, country: String, isSelected: Bool) {
self.gameStatus = gameStatus
self.country = country
self.isSelected = isSelected
}
}
func ==(left: GameInfo, right: GameInfo) -> Bool {
return
left.isSelected == right.isSelected &&
left.gameStatus == right.gameStatus &&
left.country == right.country
}
func <(left: GameInfo, right: GameInfo) -> Bool {
guard left.isSelected == right.isSelected else { return left.isSelected }
guard left.gameStatus == right.gameStatus else { return left.gameStatus < right.gameStatus }
guard left.country == right.country else { return left.country < right.country }
return true
}
Now you can just invoke sort
without the need of furthers params.
let sorted = list.sort()
Upvotes: 1