Shift Swift数组

颜色数组

let colorArray = [ UIColor.redColor(), UIColor.orangeColor(), UIColor.yellowColor(), UIColor.greenColor(), UIColor.blueColor() ] 

目标是转移数组:

  1. 以不同的颜色开始。
  2. 保留颜色的循环顺序。

示例#1

如果我们想要以橙色 (原始数组中的索引1处的颜色)开始,则数组将如下所示:

 let colorArray = [ UIColor.orangeColor(), UIColor.yellowColor(), UIColor.greenColor(), UIColor.blueColor(), UIColor.redColor(), ] 

例#2

如果我们想用绿色 (原始数组中的索引3处的颜色)开始,则数组将如下所示:

 let colorArray = [ UIColor.greenColor(), UIColor.blueColor(), UIColor.redColor(), UIColor.orangeColor(), UIColor.yellowColor() ] 

我知道这可能会迟到。 但旋转或移动数组最简单的方法是

 func shifter(shiftIndex: Int) { let strArr: [String] = ["a","b","c","d"] var newArr = strArr[shiftIndex..<strArr.count] newArr += strArr[0..<shiftIndex] println(newArr) } shifter(2) //[c, d, a, b] you can modify the function to take array as input 

您可以扩展Array来包含一个方法来返回一个数组,其中包含原始数组的元素旋转一个元素:

 extension Array { func rotate(shift:Int) -> Array { var array = Array() if (self.count > 0) { array = self if (shift > 0) { for i in 1...shift { array.append(array.removeAtIndex(0)) } } else if (shift < 0) { for i in 1...abs(shift) { array.insert(array.removeAtIndex(array.count-1),atIndex:0) } } } return array } } 

一次移动数组的元素

 let colorArray:[UIColor] = [ .redColor(), .orangeColor(), .yellowColor(), .greenColor(), .blueColor() ] let z = colorArray.rotate(1) // z is [.orangeColor(), .yellowColor(), .greenColor(), .blueColor(), .redColor()] 

和两次

 let z = colorArray.rotate(2) // z is [.yellowColor(), .greenColor(), .blueColor(), .redColor(), .orangeColor()] 

你可以通过处理起始索引来迭代。

 func iterate<T>(array:Array<T>, start:Int, callback:(T) -> ()) { let count = array.count for index in start..<(start + count) { callback(array[index % count]) } } 

如果你想从索引3开始

 iterate(colors, 3, { (color) -> () in println("color - \(color)")}) 

简短而清晰的Swift 3&4解决scheme我想出了:

 extension Array { func shifted(by shiftAmount: Int) -> Array<Element> { // 1 guard self.count > 0, (shiftAmount % self.count) != 0 else { return self } // 2 let moduloShiftAmount = shiftAmount % self.count let negativeShift = shiftAmount < 0 let effectiveShiftAmount = negativeShift ? moduloShiftAmount + self.count : moduloShiftAmount // 3 let shift: (Int) -> Int = { return $0 + effectiveShiftAmount >= self.count ? $0 + effectiveShiftAmount - self.count : $0 + effectiveShiftAmount } // 4 return self.enumerated().sorted(by: { shift($0.offset) < shift($1.offset) }).map { $0.element } } } 

说明:

  1. 没有元素和移位的数组产生原始数组的身份立即返回
  2. 为了获得有效的移位量,不pipe函数传递的数量是多less,我们进行一些模数计算,以摆脱不止一次旋转arrays中的元素的移位(例如,在具有5个对象的arrays中,移位+7与+2的移位相同)。 由于我们总是想要向右移动,所以为了用一个简单的函数而不是两个来完成,必须处理负input(例如在具有5个对象的arrays中,移位-2与移位相同+3)。 因此,我们调整模数计算的负面结果的数组长度。 当然,这3条线可以在一个,但我想尽可能使这个可读。
  3. 现在我们通过获取元素的索引( $0 )来准备实际的移位,并通过加上步骤2中计算的量来返回移位的索引。如果新索引落在数组长度之外,则需要将其包围在前面。
  4. 最后,我们将所有的准备工作应用于我们的数组中: enumerated()给了我们一个元组数组[(offset: Int, element: Int)] ,它是每个元素和元素本身的原始索引。 然后,我们通过操作offset (也就是元素的索引),通过应用来自步骤3的函数来对这个枚举数组进行sorting。最后,我们通过将sorting后的元素映射回数组中来摆脱枚举。

这个扩展与任何types的数组一起工作。 例子:

 let colorArray = [ UIColor.red, UIColor.orange, UIColor.yellow, UIColor.green, UIColor.blue ] let shiftedColorArray = [ UIColor.green, UIColor.blue, UIColor.red, UIColor.orange, UIColor.yellow ] colorArray.shifted(by: 2) == shiftedColorArray // returns true [1,2,3,4,5,6,7].shifted(by: -23) // returns [3,4,5,6,7,1,2]