2017-06-26 46 views
1

我试图扩展Array<MutatingCollection>,所以我可以镜像数组的内容,但编译器说我不能调用reverse()上的元素数组,尽管在MutatingCollection协议中定义了reverse()Array <MutableCollection>的Swift扩展将不允许reverse()

我想要做这样的事情:

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()}以及(我认为做同样的事情,但我不完全grok map())两种方式导致相同的错误消息:

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

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

Playgrounds Screenshot

也许我使用extension不当,或斯威夫特游乐场以某种方式阻碍了我的访问。

回答

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其元素是合作,将MutableCollectionBidirectionalCollection - 如[Array<Int>]甚至[ArraySlice<Int>]

可以在斯威夫特看到完整的代码reverse() 3。1这里:

Reverse.swift

延伸MutableCollection其中自:BidirectionalCollection

+0

此崩溃如果'Element'是一个可变的集合,但不是一个数组,例如为'var table = [[0,1,2] .dropFirst(),[3,4,5],[6,7,8]]',其中'Element'为'ArraySlice '。 –

+0

@MartinR我相信我已经确定了在这个问题中提出的问题的原因,并且纠正了你提到的问题。请随时检查我的正确性。 – ColGraff

+1

通过额外的约束'Indices.Iterator.Element == Index',您可以摆脱人工的'guard let index = index ...',比较https://stackoverflow.com/a/44457590/1187415或https: //stackoverflow.com/a/40331858/1187415。在Swift 4中不应该有必要。 –