简体   繁体   中英

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

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

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)

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"]

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]"

General solution:

extension Array {
   func slice(size: Int) -> [[Element]] {
      (0...(count / size)).map{Array(self[($0 * size)..<(Swift.min($0 * size + size, count))])}
   }
}

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
    }
}

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)

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))]) }
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM