【问题标题】:Swift extension of Array<MutableCollection> won't allow reverse()Array<MutableCollection> 的 Swift 扩展不允许 reverse()
【发布时间】:2017-06-26 22:23:12
【问题描述】:

我正在尝试扩展Array&lt;MutatingCollection&gt;,以便可以镜像数组数组的内容,但编译器说我不能在数组中的元素上调用reverse(),尽管reverse() 在@ 中定义987654325@协议。

我想做这样的事情:

var table = [[0,1,2],
             [3,4,5],
             [6,7,8]]
table.mirror()
//table now [[2,1,0],
//           [5,4,3],
//           [8,7,6]]

这是我的(不工作的)代码:

 extension Array where Element == MutableCollection {
        mutating func mirror() {
            for index in self.indices {
                self[index].reverse()
            }
        }
    }

我也试过self.map {array in array.reverse()}(我认为做同样的事情,但我不完全理解map())两种方式都会导致相同的错误消息:

Member 'reverse' cannot be used on value of type 'MutableCollection'

编辑:我可以直接调用相同的代码,它可以按我的预期工作。

Playgrounds Screenshot

也许我使用 extension 不正确,或者 Swift Playgrounds 以某种方式阻止了我的访问。

【问题讨论】:

    标签: arrays swift extension-methods swift-playground


    【解决方案1】:

    首先,扩展应该是这样声明的:

    extension Array where Element : MutableCollection {
    

    您想检查Element 是否遵守MutableCollection 协议,而不是MutableCollection

    但是,由于某种原因,我无法在 subscript 上调用 reverse 方法。我能做的最好的是:

    extension Array where Element : MutableCollection {
      mutating func mirror() {
        for index in self.indices {
          self[index] = self[index].reversed() as! Element
        }
      }
    }
    

    尽管强制演员表非常难看,我不喜欢这样做,但你需要它来工作。我想我应该测试演员阵容以确定但我看不到任何调用reversed() 会导致无法转换回Element 的集合。

    编辑:

    我发现了这个问题。 reverse() 方法仅在 MutableCollection 也是 BidirectionalCollection 时有效。这段代码现在可以正常工作了:

    extension MutableCollection where
      Iterator.Element : MutableCollection &
                         BidirectionalCollection,
      Indices.Iterator.Element == Index {
      mutating func mirror() {
        for index in self.indices {
          self[index].reverse()
        }
      }
    }
    

    现在代码应该适用于所有MutableCollection,其元素既是MutableCollection又是BidirectionalCollection——例如[Array&lt;Int&gt;]甚至[ArraySlice&lt;Int&gt;]

    您可以在此处查看 Swift 3.1 中 reverse() 的完整代码:

    Reverse.swift

    扩展 MutableCollection where Self : BidirectionalCollection

    【讨论】:

    • 如果Element 是一个可变集合但不是一个数组,则会崩溃,例如对于var table = [[0,1,2].dropFirst(), [3,4,5], [6,7,8]],其中ElementArraySlice&lt;Int&gt;
    • @MartinR 我相信我已经确定了这个问题中提出的问题的原因,并纠正了你提到的问题。请随时为我检查其正确性。
    • 加上一个额外的约束Indices.Iterator.Element == Index,你可以摆脱人工的guard let index = index ...,比较stackoverflow.com/a/44457590/1187415stackoverflow.com/a/40331858/1187415。在 Swift 4 中应该没有必要。
    • @MartinR 完美!我一直在寻找实现这一目标的最佳方法。谢谢。
    • 谢谢你们!
    猜你喜欢
    • 2018-04-02
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 2019-08-21
    • 1970-01-01
    • 1970-01-01
    • 2011-09-22
    • 2019-03-06
    相关资源
    最近更新 更多