在 Swift 中为 Collection 下标中的 Index 创建变异集
Create mutating set for Index in Collection subscript in Swift
我正在尝试修改此扩展以获得可变性:
extension Collection where Element: Equatable {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
indices.contains(index) ? self[index] : nil
}
}
我想实现这个工作:
var array = ["Hello", "World"]
array[safe: 5] = "Other word" // This will not be setted because index is out of bounds, but error won't be throwed.
当我尝试修改下标扩展时...
extension Collection where Element: Equatable {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index) {
self[index] = newValue <<<-- ERROR
}
}
}
}
...我收到此错误:Missing argument label 'safe:' in subscript
问题是 Collection
没有可变下标 setter。为此,您需要改为扩展 MutableCollection
。
extension MutableCollection where Element: Equatable {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript(safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index), let value = newValue {
self[index] = value
}
}
}
}
Collection
的 subscript
是只获取的。
MutableCollection
is the protocol that Array
conforms to, that declares the settable subscript
我们都知道并喜爱。毕竟,您的扩展程序要求集合是可变的,并且并非所有 Collection
都是可变的,只有 MutableCollection
是可变的。
extension MutableCollection {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index), let value = newValue {
self[index] = value
}
}
}
}
请注意,我还在 setter 中为 newValue == nil
的情况添加了检查(因为下标的类型为 Element?
,您可以将 nil
分配给它!)。在那种情况下,下标不会做任何事情。也不需要 Element : Equatable
约束。
从技术上讲,这也可以在 RangeReplaceableCollection
s 上完成,这是 Array
遵守的另一种协议。但是下标应该是O(1)时间,而replaceSubrange
不一定如此。
extension RangeReplaceableCollection {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index), let value = newValue {
self.replaceSubrange(index...index), with: CollectionOfOne(value))
}
}
}
}
我正在尝试修改此扩展以获得可变性:
extension Collection where Element: Equatable {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
indices.contains(index) ? self[index] : nil
}
}
我想实现这个工作:
var array = ["Hello", "World"]
array[safe: 5] = "Other word" // This will not be setted because index is out of bounds, but error won't be throwed.
当我尝试修改下标扩展时...
extension Collection where Element: Equatable {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index) {
self[index] = newValue <<<-- ERROR
}
}
}
}
...我收到此错误:Missing argument label 'safe:' in subscript
问题是 Collection
没有可变下标 setter。为此,您需要改为扩展 MutableCollection
。
extension MutableCollection where Element: Equatable {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript(safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index), let value = newValue {
self[index] = value
}
}
}
}
Collection
的 subscript
是只获取的。
MutableCollection
is the protocol that Array
conforms to, that declares the settable subscript
我们都知道并喜爱。毕竟,您的扩展程序要求集合是可变的,并且并非所有 Collection
都是可变的,只有 MutableCollection
是可变的。
extension MutableCollection {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index), let value = newValue {
self[index] = value
}
}
}
}
请注意,我还在 setter 中为 newValue == nil
的情况添加了检查(因为下标的类型为 Element?
,您可以将 nil
分配给它!)。在那种情况下,下标不会做任何事情。也不需要 Element : Equatable
约束。
从技术上讲,这也可以在 RangeReplaceableCollection
s 上完成,这是 Array
遵守的另一种协议。但是下标应该是O(1)时间,而replaceSubrange
不一定如此。
extension RangeReplaceableCollection {
/// Returns the element at the specified index iff it is within count, otherwise nil.
subscript (safe index: Index) -> Element? {
get {
indices.contains(index) ? self[index] : nil
}
mutating set {
if indices.contains(index), let value = newValue {
self.replaceSubrange(index...index), with: CollectionOfOne(value))
}
}
}
}