Shift Swift Array

时间:2015-07-22 05:38:32

标签: ios arrays swift

颜色数组

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

目标是转移数组:

  1. 以不同的颜色开始。
  2. 保留颜色的循环顺序。
  3. 示例#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()
    ]
    

5 个答案:

答案 0 :(得分:8)

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

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

答案 1 :(得分:4)

简短&amp;清除 Swift 3&amp; 4 解决方案我提出了:

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. 要获得有效的移位量,无论函数传递的数量多少,我们都会进行一些模数计算,以摆脱多次旋转数组中元素的移位(例如,在具有5个对象的数组中,移位+7的变化与+2的变化相同。由于我们总是想要向右移动,为了完成一个简单的功能而不是两个,必须处理负输入(例如,在具有5个对象的数组中,-2的移位与移位相同of +3)。因此,我们通过数组的长度调整模数计算的负结果。 当然,这3行可以在一个中完成,但我希望尽可能让它变得可读。
  3. 现在我们通过获取元素的索引($0)来准备实际的移位,并通过添加在步骤2中计算的数量来返回移位的索引。如果新索引落在数组长度之外,则需要被包裹在前面。
  4. 最后我们将所有准备工作应用到我们的数组中:enumerated()为我们提供了一个元组[(offset: Int, element: Int)]数组,它只是每个元素和元素本身的原始索引。然后我们通过应用第3步中的函数,通过被操纵的offset(也就是元素的索引)对这个枚举数组进行排序。最后,我们通过将已排序的元素映射回数组来摆脱枚举。 / LI>

    此扩展适用于任何类型的数组。例子:

    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]
    

答案 2 :(得分:3)

您可以扩展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()]

答案 3 :(得分:1)

您可以通过处理起始索引进行迭代。

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)")})

答案 4 :(得分:0)

@zizutg答案的一种变体,可以在两个方向(正向和负向)上移动

extension Array {
    public func shifted(by index: Int) -> Array {
        let adjustedIndex = index %% self.count

        return Array(self[adjustedIndex..<self.count] + self[0..<adjustedIndex])
    }
}

// True modulo function https://stackoverflow.com/a/41180619/683763
infix operator %%
public func %%(_ dividend: Int, _ divisor: Int) -> Int {
    precondition(divisor > 0, "modulus must be positive")
    let reminder = dividend % divisor
    return reminder >= 0 ? reminder : reminder + divisor
}