Shift Swift数组
颜色数组
let colorArray = [ UIColor.redColor(), UIColor.orangeColor(), UIColor.yellowColor(), UIColor.greenColor(), UIColor.blueColor() ]
目标是转移数组:
- 以不同的颜色开始。
- 保留颜色的循环顺序。
示例#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 } } }
说明:
- 没有元素和移位的数组产生原始数组的身份立即返回
- 为了获得有效的移位量,不pipe函数传递的数量是多less,我们进行一些模数计算,以摆脱不止一次旋转arrays中的元素的移位(例如,在具有5个对象的arrays中,移位+7与+2的移位相同)。 由于我们总是想要向右移动,所以为了用一个简单的函数而不是两个来完成,必须处理负input(例如在具有5个对象的arrays中,移位-2与移位相同+3)。 因此,我们调整模数计算的负面结果的数组长度。 当然,这3条线可以在一个,但我想尽可能使这个可读。
- 现在我们通过获取元素的索引(
$0
)来准备实际的移位,并通过加上步骤2中计算的量来返回移位的索引。如果新索引落在数组长度之外,则需要将其包围在前面。 - 最后,我们将所有的准备工作应用于我们的数组中:
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]