Swift使用filter函数按MP最值区间筛选法术列表问题
按MP消耗区间筛选法术实现方案
现有上下文代码
已定义法术相关枚举、类型别名、初始法术列表与格式化输出方法,代码如下:
enum Category: Comparable { case attack case healing case support } 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), ("Cure", .healing, 5), ("Cure 2", .healing, 25), ("Cure 3", .healing, 40), ("Regen", .healing, 10), ("Life", .healing, 30), ("Antidote", .healing, 3), ("Remedy", .healing, 15), ("Imp", .support, 10), ("Haste", .support, 10), ("Safe", .support, 12), ("Shell", .support, 15), ("Berserk", .support, 16), ("Float", .support, 17), ("Reflect", .support, 22), ("Quick", .support, 99), ("Scan", .support, 3), ("Sleep", .support, 5), ("Slow", .support, 5), ("Mute", .support, 8), ("Confuse", .support, 8), ("Stop", .support, 10) ] func spellString(_ spell: Spell) -> String { let name = spell.name.padding(toLength: 8, withPad: " ", startingAt: 0) let type: String switch spell.cat { case .attack: type = "(Attack) " case .healing: type = "(Healing)" case .support: type = "(Support)" } let cost = (spell.cost < 10) ? " " + String(spell.cost) : String(spell.cost) return "\(name) \(type) - \(cost) MP" }
需求与报错说明
需要实现逻辑:提示用户输入最小MP值与最大MP值,使用filter高阶函数筛选并打印所有MP(即cost字段)处于输入值区间内的法术。
初始编写的问题代码如下:
func selectByCost(_ spells: [Spell]) -> [Spell] { print("Enter the minimum MP cost: ") let min = readLine()! print("Enter the maximum MP cost: ") let max = readLine()! if Spell.Int == min...max { ??? } }
编译触发报错:Value of tuple type 'Spell' (aka '(name: String, cat: Category, cost: Int)') has no member 'Int'
错误原因
readLine()返回值是字符串类型,直接拿到的min、max是文本值,不能直接用于数值区间判断,必须先转为Int类型。Spell是元组类型的别名,不存在Int这个成员,Spell.Int属于非法的属性访问,要获取法术的MP消耗,需要访问单个Spell实例的cost字段。- 判断逻辑完全写反:不需要让Spell类型匹配区间,而是遍历数组中的每个Spell实例,判断它的cost值是否落在输入值构成的区间内。
正确实现代码
func selectByCost(_ spells: [Spell]) -> [Spell] { print("Enter the minimum MP cost: ") // 输入转整数,处理非法输入场景 guard let minCost = Int(readLine()!) else { print("输入的最小MP值无效,请输入整数") return [] } print("Enter the maximum MP cost: ") guard let maxCost = Int(readLine()!) else { print("输入的最大MP值无效,请输入整数") return [] } // 用filter高阶函数筛选符合区间要求的法术 let filteredSpells = spells.filter { spell in (minCost...maxCost).contains(spell.cost) } // 打印所有匹配的法术 print("=== 符合MP区间的法术列表 ===") for spell in filteredSpells { print(spellString(spell)) } return filteredSpells } // 调用示例 let result = selectByCost(startingSpellList)
关键逻辑说明
- 用
guard let做类型转换的安全校验,避免用户输入非数字内容时程序强制崩溃。 filter会遍历传入的法术数组,闭包返回true的元素会被保留到结果数组中。- 区间的
contains()方法可以直接判断数值是否落在区间内,写法比手写>=、<=双重判断更简洁易读。
内容的提问来源于stack exchange,提问作者Hehcate
相关产品推荐
相关产品推荐

