Reputation: 271824
var mentions = ["@alex", "@jason", "@jessica", "@john"]
I want to limit my array to 3 items, so I want to splice it:
var slice = [String]()
if mentions.count > 3 {
slice = mentions[0...3] //alex, jason, jessica
} else {
slice = mentions
}
However, I'm getting:
Ambiguous subscript with base type '[String]' and index type 'Range'
Apple Swift version 2.2 (swiftlang-703.0.18.8 clang-703.0.31) Target: x86_64-apple-macosx10.9
Upvotes: 43
Views: 66896
Reputation: 833
General solution:
extension Array {
func slice(size: Int) -> [[Element]] {
(0..<(count / size + (count % size == 0 ? 0 : 1))).map{Array(self[($0 * size)..<(Swift.min($0 * size + size, count))])}
}
}
Corrected for extra slice in case of array size is multiple of slice size as mentioned by @mahbaleshwarhegde
Upvotes: 3
Reputation: 839
Array slice func extension:
extension Array {
func slice(with sliceSize: Int) -> [[Element]] {
guard self.count > 0 else { return [] }
var range = self.count / sliceSize
if self.count.isMultiple(of: sliceSize) {
range -= 1
}
return (0...range).map { Array(self[($0 * sliceSize)..<(Swift.min(($0 + 1) * sliceSize, self.count))]) }
}
}
Upvotes: 0
Reputation: 39
You can also slice like this:
//Generic Method
func slice<T>(arrayList:[T], limit:Int) -> [T]{
return Array(arrayList[..<limit])
}
//How to Use
let firstThreeElements = slice(arrayList: ["@alex", "@jason", "@jessica", "@john"], limit: 3)
Upvotes: 0
Reputation: 1637
I came up with this:
public extension Array {
func slice(count: Int) -> [some Collection] {
let n = self.count / count // quotient
let i = n * count // index
let r = self.count % count // remainder
let slices = (0..<n).map { $0 * count }.map { self[$0 ..< $0 + count] }
return (r > 0) ? slices + [self[i..<i + r]] : slices
}
}
Upvotes: 0
Reputation: 81
You can try .prefix(). Returns a subsequence, up to the specified maximum length, containing the initial elements of the collection. If the maximum length exceeds the number of elements in the collection, the result contains all the elements in the collection.
let numbers = [1, 2, 3, 4, 5]
print(numbers.prefix(2)) // Prints "[1, 2]"
print(numbers.prefix(10)) // Prints "[1, 2, 3, 4, 5]"
Upvotes: 6
Reputation: 780
We can do like this,
let arr = [10,20,30,40,50]
let slicedArray = arr[1...3]
if you want to convert sliced array to normal array,
let arrayOfInts = Array(slicedArray)
Upvotes: 18
Reputation: 459
Can also look at dropLast() function:
var mentions:[String] = ["@alex", "@jason", "@jessica", "@john"]
var slice:[String] = mentions
if mentions.count > 3 {
slice = Array(mentions.dropLast(mentions.count - 3))
}
//print(slice) => ["@alex", "@jason", "@jessica"]
Upvotes: 2
Reputation: 80811
The problem is that mentions[0...3]
returns an ArraySlice<String>
, not an Array<String>
. Therefore you could first use the Array(_:)
initialiser in order to convert the slice into an array:
let first3Elements : [String] // An Array of up to the first 3 elements.
if mentions.count >= 3 {
first3Elements = Array(mentions[0 ..< 3])
} else {
first3Elements = mentions
}
Or if you want to use an ArraySlice
(they are useful for intermediate computations, as they present a 'view' onto the original array, but are not designed for long term storage), you could subscript mentions
with the full range of indices in your else
:
let slice : ArraySlice<String> // An ArraySlice of up to the first 3 elements
if mentions.count >= 3 {
slice = mentions[0 ..< 3]
} else {
slice = mentions[mentions.indices] // in Swift 4: slice = mentions[...]
}
Although the simplest solution by far would be just to use the prefix(_:)
method, which will return an ArraySlice
of the first n elements, or a slice of the entire array if n exceeds the array count:
let slice = mentions.prefix(3) // ArraySlice of up to the first 3 elements
Upvotes: 78