По крайней мере, в Геккосе это возможно. Посмотрите здесь:
edit: Я не мог заставить это работать; похоже, что Гарет прав ...
Учитывая ваш вариант использования, в котором вы всегда проверяете [113].<prop> == newthing.<prop>
, вы можете поднять это немного больше, добавив:
mutating func replaceOrAppend<Value>(_ item: Element,
firstMatchingKeyPath keyPath: KeyPath<Element, Value>)
where Value: Equatable
{
let itemValue = item[keyPath: keyPath]
replaceOrAppend(item, whereFirstIndex: { [110][keyPath: keyPath] == itemValue })
}
Затем вы можете использовать его как:
[111 ]И, конечно, если вы делаете это много, вы можете продолжать подниматься и подниматься.
protocol Identifiable {
var id: Int { get }
}
extension Student: Identifiable {}
extension Array where Element: Identifiable {
mutating func replaceOrAppendFirstMatchingID(_ item: Element)
{
replaceOrAppend(item, firstMatchingKeyPath: \.id)
}
}
array.replaceOrAppendFirstMatchingID(alice0) // [alice1, alice0]
Предполагая, что ваши типы являются уравняемыми, это общее расширение:
extension RangeReplaceableCollection where Element: Equatable {
mutating func addOrReplace(_ element: Element) {
if let index = self.firstIndex(of: element) {
self.replaceSubrange(index...index, with: [element])
}
else {
self.append(element)
}
}
}
Однако имейте в виду, что моя (и ваша) функция заменит только один соответствующих элементов.
Испытание на полной рабочей площадке: