Home > Net >  Error when using higher order function reduce
Error when using higher order function reduce

Time:12-18

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
}
  • Related