Issue
I want to create a generic function to sort an array of classes based on a property passed.
For example, I have these classes
public class Car {
var id: Int
var manufacturer: String
var variant: String
init(id: Int, manufacturer: String, variant: String) {
self.id = id
self.manufacturer = manufacturer
self.variant = variant
}
}
enum Gender {
case male
case female
}
public class Person {
var id: Int
var name: String
var age: Int
var gender: Gender
init(id: Int, name: String, age: Int, gender: Gender) {
self.id = id
self.name = name
self.age = age
self.gender = gender
}
}
And these arrays,
let cars = [
Car(id: 1, manufacturer: "Ford", variant: "Focus"),
Car(id: 2, manufacturer: "Nissan", variant: "Skyline"),
Car(id: 3, manufacturer: "Dodge", variant: "Charger"),
Car(id: 4, manufacturer: "Chevrolet", variant: "Camaro"),
Car(id: 5, manufacturer: "Ford", variant: "Shelby")
]
let persons = [
Person(id: 1, name: "Ed Sheeran", age: 26, gender: .male),
Person(id: 2, name: "Phil Collins", age: 66, gender: .male),
Person(id: 3, name: "Shakira", age: 40, gender: .female),
Person(id: 4, name: "Rihanna", age: 25, gender: .female),
Person(id: 5, name: "Bono", age: 57, gender: .male)
]
How to write a generic extension for the array, to sort it based on the property passed? (eg. persons.sort(name) or cars.sort(manufacturer))
Thanks!
Solution
Here you go:
extension Array {
mutating func propertySort<T: Comparable>(_ property: (Element) -> T) {
sort(by: { property($0) < property($1) })
}
}
Usage:
persons.propertySort({$0.name})
And here is a non-mutating version:
func propertySorted<T: Comparable>(_ property: (Element) -> T) -> [Element] {
return sorted(by: {property($0) < property($1)})
}
As Leo Dabus pointed out, you can generalise the extension to any MutableCollection
that is also a RandomAccessCollection
:
extension MutableCollection where Self : RandomAccessCollection {
...
Answered By – Sweeper
Answer Checked By – Katrina (BugsFixing Volunteer)