I am working on a function that takes the total cost of all the "MP" in a value and adds it up. Here is my code for context.
typealias Spell = (name: String, cat: Category, cost: Int)
let startingSpellList: [Spell] = [
("Poison", .attack, 3),
("Bio", .attack, 26),
("Fire", .attack, 4),
("Fire 2", .attack, 20),
("Fire 3", .attack, 51),
("Ice", .attack, 5),
("Ice 2", .attack, 21),
("Ice 3", .attack, 52),
("Bolt", .attack, 6),
("Bolt 2", .attack, 22),
("Bolt 3", .attack, 53),
("Pearl", .attack, 40),
("Quake", .attack, 50),
("Break", .attack, 25),
("Doom", .attack, 35),
("Flare", .attack, 45),
("Meteor", .attack, 62),
("Ultima", .attack, 80),
Here is the function :
func totalCost(_ spells: [Spell]) -> Int {
let cost = spells.cost
let sum = cost.reduce(0, )
return sum
}
With this code, I get the error that `"Value of type '[Spell]' (aka 'Array<(name: String, cat: Category, cost: Int)>') has no member 'cost'." How should I fix this error?
CodePudding user response:
spells
is a [Spell]
, which is shorthand for Array<Spell>
, and Array<Spell>
doesn't have a cost
property. Each individual Spell
in the array has its own cost
property. You could say this to get an array of the spell costs and sum the costs array:
func totalCost(_ spells: [Spell]) -> Int {
let costs = spells.map { $0.cost }
let sum = costs.reduce(0, )
return sum
}
Or you could use a key-path literal, which can act as a function:
func totalCost(_ spells: [Spell]) -> Int {
let costs = spells.map(\.cost)
let sum = costs.reduce(0, )
return sum
}
However, using map
that way creates a temporary array to hold the costs, and that's wasteful. You can avoid the temporary array by using the .lazy
operator first:
func totalCost(_ spells: [Spell]) -> Int {
let costs = spells.lazy.map(\.cost)
let sum = costs.reduce(0, )
return sum
}
Or you can fuse the extraction of cost
and the summation:
func totalCost(_ spells: [Spell]) -> Int {
let sum = spells.reduce(0) { $0 $1.cost }
return sum
}