5

Say I have an array of 5 Ints. What would be the most efficient way to wrap the index of the array if the index were incremented or decremented (for example) the following occurs?

where n = 0: arr[n-1] // -> arr[4] (wraps from 0 back to the end of the array)

where n = 2: arr[n+1] // -> arr[3] (behaves as normal)

where n = 4: arr[n+1] // -> arr[0] (wraps to 0 from the end of the array)

Aaron
  • 6,466
  • 7
  • 37
  • 75

3 Answers3

7

You can use the mod operation which will get you to a range of -count to count, then add count back in and mod again:

let foo = [0, 1, 2, 3, 4, 5]

for i in -6...7 {
  print(i, foo[(i % foo.count + foo.count) % foo.count])
}

//  -6 0
//  -5 1
//  -4 2
//  -3 3
//  -2 4
//  -1 5
//  0 0
//  1 1
//  2 2
//  3 3
//  4 4
//  5 5
//  6 0

This works for both directions.

  • This is the magic I was looking for: `foo[(n % foo.count + foo.count) % foo.count]` where `n+1` and `n-1` both wrap properly. Thank you. – Aaron Jul 30 '17 at 08:14
1

A bit late to the party, but if you're facing the same issue and have a lot of use cases for wrap-around array indices, you could also put the %-solution from the accepted answer in a simple subscript extension of Array, like so:

extension Array {
    subscript (wrapping index: Int) -> Element {
        return self[(index % self.count + self.count) % self.count]
    }
}

Example Usage:

let array = ["a","b","c"]
print( array[wrapping: 0] )   // a
print( array[wrapping: 4] )   // b
print( array[wrapping: -1] )  // c
Gamma
  • 1,347
  • 11
  • 18
0

Cleanest I can do for only positive integers is this

extension Array{
    subscript(wrapAround index: Int) -> Element {
        return self[index % self.count]
    }
}
Will
  • 4,942
  • 2
  • 22
  • 47