I have a struct containing a bunch of properties referencing different types of statistics. A sample object is:
class Stats {
stats: [Stat]
}
struct Stat {
id: UUID
countA: Int
countB: Int
countC: Int
totalAAttempts: Int
totalBAttempts: Int
totalCAttempts: Int
...
}
I am displaying the percentages with a bunch of functions in the class…
class Stats {
stats: [Stat]
var countAPerc: Double {
let totalA = stats.reduce(0) { total, stat in
total + stat.countA
}
let totalAttemps = s.reduce(0) { total, stat in
total + stat.totalAAttempts
}
return Double(totalA) / Double(totalAttempts)
}
var: countAPercDisplay: String {
String(format: "%.1f", countAPerc * 100) + "%"
}
var countBPerc: Double {
let totalB = stats.reduce(0) { total, stat in
total + stat.countB
}
let totalAttemps = s.reduce(0) { total, stat in
total + stat.totalBAttempts
}
return Double(totalB) / Double(totalAttempts)
}
var: countBPercDisplay: String {
String(format: "%.1f", countBPerc * 100) + "%"
}
...
}
Is it possible to specify the name of the property as a parameter in a function to prevent the same code from being written over and over? Something like:
func summarizeProperty(_ countProperty: PROPERTYNAME1, _ totalProperty: PROPERTYNAME2) -> Double {
let totalCount = stats.reduce(0) { total, stat in
total + stat.PROPERTYNAME1
}
let totalAttemps = s.reduce(0) { total, stat in
total + stat.PROPERTYNAME2
}
return Double(totalCount) / Double(totalAttempts)
}
func summarizedProperty(_ countProperty: PROPERTYNAME1, _ totalProperty: PROPERTYNAME2) -> String {
let summarized = summarizeProperty(PROPERTYNAME1, PROPERTYNAME2)
return String(format: "%.1f", summarized * 100) + "%"
}
And then call it…
Text(summarizedProperty(countA, totalAAttempts))
Thanks in advance
>Solution :
The tool you want here is a KeyPath:
func summarizeProperty(_ countProperty: KeyPath<Stat, Int>, _ totalProperty: KeyPath<Stat, Int>) -> Double {
let totalCount = stats.reduce(0) { total, stat in
total + stat[keyPath: countProperty]
}
let totalAttempts = stats.reduce(0) { total, stat in
total + stat[keyPath: totalProperty]
}
return Double(totalCount) / Double(totalAttempts)
}
A KeyPath<Stat, Int> is property on Stat that returns an Int. It is accessed using the keyPath: subscript and generally created using the \ syntax :
Stats().summarizeProperty(\.countA, \.totalAAttempts)
KeyPaths are normal values and can be passed around like this:
func summarizedProperty(_ countProperty: KeyPath<Stat, Int>, _ totalProperty: KeyPath<Stat, Int>) -> String {
let summarized = summarizeProperty(countProperty, totalProperty)
return String(format: "%.1f", summarized * 100.0) + "%"
}