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
Answer from Hamish on Stack OverflowThe 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
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)
Why does Swift have an ArraySlice type that is not interchangeable with the Array type? Isn't an array slice an optimization that is best hidden from the programmer?
Swift has taken the approach where a sliced collection is simple a view into the storage of the original collection, rather than eagerly copying its elements into a new Array. The reason to have a specific ArraySlice type is so you are aware of the memory management around the contents of the original array – the slice is holding a strong reference to it, so it will stay alive even after other references have disappeared. This gives you control over when a copy occurs so you can optimise performance and memory usage.
This is explained further by Ben Cohen in What's New in Swift - WWDC 17 at 35 minutes in, which covers slicing strings but also applies to arrays and other collections.
More on reddit.comFunctions that accept arrays or array slices - Using Swift - Swift Forums
[Rant] Indexing into ArraySlice - Using Swift - Swift Forums
What is the purpose of Swift's ArraySlice or SubArray, other than to avoid a performance penalty of copying?
Update: Now that I have a better understanding of the issue from your comments below, I think this is premature optimization.
IMO, slicing by eagerly copying the elements into an Array type would be better as the default behavior. If you want something more efficient, then perhaps you could use an explicit ArraySlice type annotation, much like how you would use an explicit Character type annotation if you don't want a string.
Swift has taken the approach where a sliced collection is simple a view into the storage of the original collection, rather than eagerly copying its elements into a new Array. The reason to have a specific ArraySlice type is so you are aware of the memory management around the contents of the original array – the slice is holding a strong reference to it, so it will stay alive even after other references have disappeared. This gives you control over when a copy occurs so you can optimise performance and memory usage.
This is explained further by Ben Cohen in What's New in Swift - WWDC 17 at 35 minutes in, which covers slicing strings but also applies to arrays and other collections.
My understanding is that there isn't a known way to hide it without making it meaningfully less effective as an optimization.