In Swift, is there a clever way of using the higher order methods on Array to return the 5 first objects? The obj-c way of doing it was saving an index, and for-loop throug
SWIFT 4
A different solution:
An easy inline solution that wont crash if your array is too short
[0,1,2,3,4,5].enumerated().compactMap{ $0.offset < 3 ? $0.element : nil }
But works fine with this.
[0,1,2,3,4,5].enumerated().compactMap{ $0.offset < 1000 ? $0.element : nil }
Usually this would crash if you did this:
[0,1,2,3,4,5].prefix(upTo: 1000) // THIS CRASHES
[0,1,2,3,4,5].prefix(1000) // THIS DOESNT
I slightly changed Markus' answer to update it for the latest Swift version, as var
inside your method declaration is no longer supported:
extension Array {
func takeElements(elementCount: Int) -> Array {
if (elementCount > count) {
return Array(self[0..<count])
}
return Array(self[0..<elementCount])
}
}
Update:
There is now the possibility to use prefix
to get the first n elements of an array. Check @mluisbrown's answer for an explanation how to use prefix.
Original Answer:
You can do it really easy without filter
, map
or reduce
by just returning a range of your array:
var wholeArray = [1, 2, 3, 4, 5, 6]
var n = 5
var firstFive = wholeArray[0..<n] // 1,2,3,4,5
For getting the first 5 elements of an array, all you need to do is slice the array in question. In Swift, you do it like this: array[0..<5]
.
To make picking the N first elements of an array a bit more functional and generalizable, you could create an extension method for doing it. For instance:
extension Array {
func takeElements(var elementCount: Int) -> Array {
if (elementCount > count) {
elementCount = count
}
return Array(self[0..<elementCount])
}
}
For an array of objects you can create an extension from Sequence.
extension Sequence {
func limit(_ max: Int) -> [Element] {
return self.enumerated()
.filter { $0.offset < max }
.map { $0.element }
}
}
Usage:
struct Apple {}
let apples: [Apple] = [Apple(), Apple(), Apple()]
let limitTwoApples = apples.limit(2)
// limitTwoApples: [Apple(), Apple()]
By far the neatest way to get the first N elements of a Swift array is using prefix(_ maxLength: Int)
:
let someArray = [1, 2, 3, 4, 5, 6, 7]
let first5 = someArray.prefix(5) // 1, 2, 3, 4, 5
This has the benefit of being bounds safe. If the count you pass to prefix
is larger than the array count then it just returns the whole array.
NOTE: as pointed out in the comments, Array.prefix
actually returns an ArraySlice
, not an Array
. In most cases this shouldn't make a difference but if you need to assign the result to an Array
type or pass it to a method that's expecting an Array
param you will need to force the result into an Array
type: let first5 = Array(someArray.prefix(5))