如果您坚持使用值类型方法(并且鉴于 identifier 不是唯一的:否则,请考虑使用字典进行简单的提取和替换逻辑),您可以为拥有的类型编写一个变异函数[Instruments] 数组,它在数组中找到(第一个)Instrument 实例,并使用提供的闭包对其进行变异。例如。 (感谢@Hamish 的改进!):
struct Instrument {
let identifier: String
var changeThis: Int
init(_ identifier: String, _ changeThis: Int) {
self.identifier = identifier
self.changeThis = changeThis
}
}
struct Foo {
var instruments: [Instrument]
@discardableResult // do not necessarily make use of the return result (no warning if not)
mutating func updateInstrument(forFirst identifier: String,
using mutate: (inout Instrument) -> ()) -> Bool {
if let idx = instruments.indices
.first(where: { instruments[$0].identifier == identifier }) {
// mutate this instrument (in-place) using supplied closure
mutate(&instruments[idx])
return true // replacement successful
}
return false // didn't find such an instrument
}
}
示例用法:
var foo = Foo(instruments:
[Instrument("a", 1), Instrument("b", 2),
Instrument("c", 3), Instrument("b", 4)])
// make use of result of call
if foo.updateInstrument(forFirst: "b", using: { $0.changeThis = 42 }) {
print("Successfully mutated an instrument")
} // Successfully mutated an instrument
// just attempt mutate and discard the result
foo.updateInstrument(forFirst: "c", using: { $0.changeThis = 99 })
print(foo.instruments)
/* [Instrument(identifier: "a", changeThis: 1),
Instrument(identifier: "b", changeThis: 42),
Instrument(identifier: "c", changeThis: 99),
Instrument(identifier: "b", changeThis: 4)] */
如@Owen:s answer 所示,找到元素上某个谓词的第一个索引的更简洁的方法是使用数组的index(where:) 方法(而不是上面使用的indices.first(where:))。在上面的完整示例中使用index(where:) 方法只对应于替换
if let idx = instruments.indices
.first(where: { instruments[$0].identifier == identifier }) { ...
与
if let idx = instruments
.index(where: { $0.identifier == identifier }) { ...
在Foo的updateInstrument(forFirst:using)方法中。
我们可以进一步压缩updateInstrument(forFirst:using) 方法,通过应用Optional 的map 函数在一行中执行(可能的)替换和布尔返回:
struct Foo {
var instruments: [Instrument]
@discardableResult
mutating func updateInstrument(forFirst identifier: String,
using mutate: (inout Instrument) -> ()) -> Bool {
return instruments
.index(where: { $0.identifier == identifier })
.map { mutate(&instruments[$0]) } != nil
}
}