swift函数迭代可能反转的数组

时间:2015-12-01 18:02:49

标签: swift

我想创建一个迭代数组(或集合或序列)的函数。然后我将用一个数组调用该函数,并调用该数组的反转版本(但效率很高:没有创建一个新数组来保持反向)。

如果我这样做:

func doIteration(points: [CGPoint]) {
  for p in points {
     doSomethingWithPoint(p)
  }
  // I also need random access to points
  doSomethingElseWithPoint(points[points.count-2]) // ignore obvious index error
}

如果我有这个:

let points : [CGPoint] = whatever

我可以做得很好:

doIteration(points)

但是如果我这样做的话:

doIteration(points.reverse())

我得到'无法转换类型的值'ReverseRandomAccessCollection< [CGPoint]>预期参数类型[_]'

现在,我不想这样做:

let reversedPoints : [CGPoint] = points.reverse()
doIteration(reversedPoints)

即使它会起作用,因为那会(如果我错了就纠正我)创建一个新数组,从reverse()返回的ReverseRandomAccessCollection初始化它。

所以我想我想编写我的doIteration函数来获取某种序列类型,所以我可以直接传递reverse()的结果,但是ReverseRandomAccessCollection根本不符合任何东西。我想我错过了什么 - 这里接受的模式是什么?

2 个答案:

答案 0 :(得分:2)

如果您将参数的类型更改为通用类型,则应获得所需的功能:

func doIteration
  <C: CollectionType where C.Index: RandomAccessIndexType,  C.Generator.Element == CGPoint>
  (points: C) {
  for p in points {
    doSomethingWithPoint(p)
  }
  doSomethingElseWithPoint(points[points.endIndex - 2])
}

更重要的是,这个不会导致数组的副本。如果查看reverse()方法生成的类型:

let points: [CGPoint] = []

let reversed = points.reverse() // ReverseRandomAccessCollection<Array<__C.CGPoint>>

doIteration(reversed)

你会看到它只是创建了一个引用原始数组的结构。 (虽然它确实有值类型语义)并且由于正确的通用约束,原始函数可以接受这个新集合。

答案 1 :(得分:0)

你可以这样做

let reversedPoints : [CGPoint] = points.reverse()
doIteration(reversedPoints)

或者

doIteration(points.reverse() as [CGPoint])

但我不认为足迹的观点存在任何真正的差异。

场景1

let reversedPoints : [CGPoint] = points.reverse()
doIteration(reversedPoints)

实际上,在这种情况下,会创建一个包含引用的新数组到原始数组中的CGPoint(s)。这要归功于Swift用于管理结构的写时复制机制。

所以分配的内存如下:

  

points.count * sizeOf(指针)

场景2

另一方面,你可以写这样的东西

doIteration(points.reverse() as [CGPoint])

但你真的在挽救记忆吗?让我们来看看。 创建一个临时变量,该变量在函数doIteration的范围内 可用,并且只需要points中包含的每个元素的指针,所以我们再次:

  

points.count * sizeOf(指针)

所以我认为您可以安全地选择其中一种解决方案。

考虑

我们应该记住,Swift以非常聪明的方式管理结构。

写作时

var word = "Hello"
var anotherWord = word

在第一行Swift创建一个Struct并用值“Hello”填充它。 在第二行,Swift检测到没有真正的理由来创建原始String的副本,因此在anotherWord内写入对原始值的引用。

只有在修改wordanotherWord时,Swift才会真正创建原始值的副本。