Reputation: 353
I have a dictionary which has a key I'd like to do multiple sort on. One key, however, can't be sorted alphabetically or it would not make sense. Those keys can have only a defined set of values, and I'm trying to sort using a specified order.
The second sort is easy, so I can use the sort descriptor way, which works fine:
let costSort = NSSortDescriptor( key: "cmc", ascending: false )
let sortDescriptors = [costSort]
let sortedCards = cards.sortedArrayUsingDescriptors( sortDescriptors )
The other key must be ordered in particular order specified by an array:
let rarity = ["Special", "Mythic rare", "Rare", "Uncommon", "Common", "Basic Land"]
So, not in alphabetical order at all, yet I need to make sure that the sort follows this ordering. I'm unsure how to code it.
Example records:
let cards = [
["name": "card1", "rarity": "Common", "cmc": 2],
["name": "card2", "rarity": "Rare", "cmc": 4],
["name": "card3", "rarity": "Common", "cmc": 1],
["name": "card4", "rarity": "Mythic rare", "cmc": 8]
]
The goal is that the sorted result, using [raritySort,costSort] would be:
card4
card2
card1
card3
Upvotes: 1
Views: 160
Reputation: 329
What about this?
let sortedCards = cards.sorted { (d1, d2) -> Bool in
d1.valueForKey("cmc") as Int > d2.valueForKey("cmc") as Int
}
Ok, what about this?
var cards = [
["name": "card1", "rarity": "Common", "cmc": 2],
["name": "card2", "rarity": "Rare", "cmc": 4],
["name": "card3", "rarity": "Common", "cmc": 1],
["name": "card4", "rarity": "Mythic rare", "cmc": 8]
]
let rarity = ["Special": 1, "Mythic rare": 2, "Rare": 3, "Uncommon": 4, "Common": 5, "Basic Land": 6]
let sortedCards = cards.sorted { (d1, d2) -> Bool in
let d1R: Int = rarity[d1.valueForKey("rarity") as String]!
let d2R: Int = rarity[d2.valueForKey("rarity") as String]!
if d1R == d2R {
return d1.valueForKey("cmc") as Int > d2.valueForKey("cmc") as Int
} else {
return d1R < d2R
}
}
Upvotes: 0
Reputation: 64644
Here's a possible solution. Is uses Swift's sorted method and a closure instead of an NSSortDescriptor.
var cards = [
["name": "card1", "rarity": "Common", "cmc": 2],
["name": "card2", "rarity": "Rare", "cmc": 4],
["name": "card3", "rarity": "Common", "cmc": 1],
["name": "card4", "rarity": "Mythic rare", "cmc": 8]
]
let rarity = ["Special", "Mythic rare", "Rare", "Uncommon", "Common", "Basic Land"]
var sortedCards = sorted(cards) {
find(rarity, $0["rarity"] as String) > find(rarity, $1["rarity"] as String) || $0["cmc"] as Int >= $1["cmc"] as Int
}
println(sortedCards)
I used the more concise closure syntax here. You could also expand it like this:
var sortedCards = sorted(cards, { (d1, d2) -> Bool in
if find(rarity, d1["rarity"] as String) > find(rarity, d2["rarity"] as String){
return true
}
return d1["cmc"] as Int >= d2["cmc"] as Int
})
Upvotes: 2
Reputation: 32054
If you want to use the NSArray
sort methods, you can do something like this using an NSSortDescriptor
based on a custom NSComparator
that looks up the indexes of the rarities in your array, and uses them to determine relative rank/ordering:
let rarities = ["Special", "Mythic rare", "Rare", "Uncommon", "Common", "Basic Land"]
let cards = [
["name": "card1", "rarity": "Common", "cmc": 2],
["name": "card2", "rarity": "Rare", "cmc": 4],
["name": "card3", "rarity": "Common", "cmc": 1],
["name": "card5", "rarity": "Common", "cmc": 7],
["name": "card6", "rarity": "Common", "cmc": 0],
["name": "card4", "rarity": "Mythic rare", "cmc": 8]
]
let nsarrayCards = cards as NSArray
let costSort = NSSortDescriptor( key: "cmc", ascending: false )
let raritySort = NSSortDescriptor(key: "rarity", ascending: false, comparator: { (leftRarity, rightRarity) -> NSComparisonResult in
if let leftRarityIdx = find(rarities, leftRarity as String) {
if let rightRarityIdx = find(rarities, rightRarity as String) {
if rightRarityIdx == leftRarityIdx {
return .OrderedSame
}
return leftRarityIdx > rightRarityIdx ? .OrderedAscending : .OrderedDescending
}
}
return .OrderedSame
})
let sortDescriptors = [raritySort, costSort]
let sortedCards = nsarrayCards.sortedArrayUsingDescriptors( sortDescriptors )
At the end here, sortedCards
contains:
[{
cmc = 8;
name = card4;
rarity = "Mythic rare";
}, {
cmc = 4;
name = card2;
rarity = Rare;
}, {
cmc = 7;
name = card5;
rarity = Common;
}, {
cmc = 2;
name = card1;
rarity = Common;
}, {
cmc = 1;
name = card3;
rarity = Common;
}, {
cmc = 0;
name = card6;
rarity = Common;
}]
Upvotes: 2