how do I sort an NSMutableSet in Swift?

147 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
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
}