Array<MutableCollection> 的 Swift 扩展不允许 reverse()

Posted

技术标签:

【中文标题】Array<MutableCollection> 的 Swift 扩展不允许 reverse()【英文标题】:Swift extension of Array<MutableCollection> won't allow 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 以某种方式阻止了我的访问。

【问题讨论】:

【参考方案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 ...,比较***.com/a/44457590/1187415或***.com/a/40331858/1187415。在 Swift 4 中应该没有必要。 @MartinR 完美!我一直在寻找实现这一目标的最佳方法。谢谢。 谢谢你们!

以上是关于Array<MutableCollection> 的 Swift 扩展不允许 reverse()的主要内容,如果未能解决你的问题,请参考以下文章

为啥 std::array<int, 10> x 不是零初始化但 std::array<int, 10> x = std::array<int, 10>() 似乎是

hdu 6197 array array array LIS

boost Array Example

如何使用 Eigen 3 表达“<array-of-true-or-false> = <array> <= <scalar>”?

PySpark Array<double> 不是 Array<double>

std::array<> 的初始化