TIMEX
TIMEX

Reputation: 271824

How can I perform an Array Slice in Swift?

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

Answers (8)

Björn B.
Björn B.

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

Ali Hamad
Ali Hamad

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

Rajesh Kumar Sahil
Rajesh Kumar Sahil

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

Kaz Yoshikawa
Kaz Yoshikawa

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

Ilya Valito
Ilya Valito

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

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

Matt
Matt

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

Hamish
Hamish

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

Related Questions