In Swift, what's the cleanest way to get the last two items in an Array?

zekel picture zekel · Jun 23, 2015 · Viewed 31.4k times · Source

Is there a cleaner way to get the last two items of an array in Swift? In general, I try to avoid this approach since it's so easy to be off-by-one with the indexes. (Using Swift 1.2 for this example.)

// Swift -- slices are kind of a hassle?
let oneArray = ["uno"]
let twoArray = ["uno", "dos"]
let threeArray = ["uno", "dos", "tres"]

func getLastTwo(array: [String]) -> [String] {
    if array.count <= 1 {
        return array
    } else {
        let slice: ArraySlice<String> = array[array.endIndex-2..<array.endIndex]
        var lastTwo: Array<String> = Array(slice)
        return lastTwo
    }
}

getLastTwo(oneArray)   // ["uno"]
getLastTwo(twoArray)   // ["uno", "dos"]
getLastTwo(threeArray) // ["dos", "tres"]

I was hoping for something closer to Python's convenience.

## Python -- very convenient slices
myList = ["uno", "dos", "tres"]
print myList[-2:] # ["dos", "tres"]

Answer

Imanou Petit picture Imanou Petit · Oct 22, 2015

With Swift 5, according to your needs, you may choose one of the following patterns in order to get a new array from the last two elements of an array.


#1. Using Array's suffix(_:)

With Swift, objects that conform to Collection protocol have a suffix(_:) method. Array's suffix(_:) has the following declaration:

func suffix(_ maxLength: Int) -> ArraySlice<Element>

Returns a subsequence, up to the given maximum length, containing the final elements of the collection.

Usage:

let array = [1, 2, 3, 4]
let arraySlice = array.suffix(2)
let newArray = Array(arraySlice)
print(newArray) // prints: [3, 4]

#2. Using Array's subscript(_:)

As an alternative to suffix(_:) method, you may use Array's subscript(_:) subscript:

let array = [1, 2, 3, 4]
let range = array.index(array.endIndex, offsetBy: -2) ..< array.endIndex
//let range = array.index(array.endIndex, offsetBy: -2)... // also works
let arraySlice = array[range]
let newArray = Array(arraySlice)
print(newArray) // prints: [3, 4]