how do I sort an NSMutableSet in Swift?

150 Views Asked by At

I am trying to use a NSMutableOrderedSet to store some data, but I would like to sort the set by a specific attribute. I tried to look online on how to use the sort(comparator cmptr: (Any, Any) -> ComparisonResult) function of the NSMutableOrderedSet but I am unsure on how to use this. I would like to know if someone could give me a quick example I was unable to find any tutorials or examples on Apples developer documentation.

Currently I have:

jersey.swift:

    struct Jersey{
       var name: String
       var number: Int
}

viewcontroller.swift:

let firstBasemanJersey = Jersey(name: "Bob", number: 5)
let secondBasemanJersey = Jersey(name: "Jim", number: 15)
let thirdBasemanJersey = Jersey(name: "Jon", number: 1)
let catcherJersey = Jersey(name: "Steve", number: 79)

var jerseySet = NSMutableOrderedSet()
jerseySet.addObject(firstBasemanJersey)
jerseySet.addObject(secondBasemanJersey)
jerseySet.addObject(thirdBasemanJersey)
jerseySet.addObject(catcherJersey)

I would like to sort the set by the jersey.number would someone be able to show me how would I use the

self.something.sort { (<#Any#>, <#Any#>) -> ComparisonResult in
            <#code#>
        }
1

There are 1 best solutions below

0
Alladinian On

In the most basic form you just have to compare the two arguments (a pair of Any objects since the Set doesn't 'know' what objects is currently holding) and return a ComparisonResult that can be either orderedAscending, orderedDescending or orderedSame:

jerseySet.sort(comparator: { lhs, rhs in
    guard let (l, r) = (lhs, rhs) as? (Jersey, Jersey) else { return .orderedSame }
    guard l.number != r.number else { return .orderedSame }
    return l.number < r.number  ? .orderedAscending : .orderedDescending
}) 

now if you print(jerseySet.array):

[Jerseys.Jersey(name: "Jon", number: 1), Jerseys.Jersey(name: "Bob", number: 5), Jerseys.Jersey(name: "Jim", number: 15), Jerseys.Jersey(name: "Steve", number: 79)]

And (for the reasons mentioned in the question comments) here is a "Swiftier" version of this:

struct Jersey: Hashable {
   let name: String
   let number: Int
}

let firstBasemanJersey  = Jersey(name: "Bob", number: 5)
let secondBasemanJersey = Jersey(name: "Jim", number: 15)
let thirdBasemanJersey  = Jersey(name: "Jon", number: 1)
let catcherJersey       = Jersey(name: "Steve", number: 79)

// Kept as var assuming that you will later `.insert` things in the set
var jerseySet = Set([
    firstBasemanJersey,
    secondBasemanJersey,
    thirdBasemanJersey,
    catcherJersey
])

let sortedByNumber = jerseySet.sorted { lhs, rhs in
    lhs.number < rhs.number
}