Swift equivalent to each_slice

前端 未结 3 347
轻奢々
轻奢々 2021-01-23 13:00

Is there something similar to Ruby\'s Enumerable#each_slice in Swift?

Ruby example:

arr = [\"a\", \"b\", \"c\", \"d\"]
arr.each_slice(2) {|s1, s2| puts s         


        
相关标签:
3条回答
  • 2021-01-23 13:39

    To amend my comment:

    let a = ["a", "b", "c", "d"]
    for var i = 0; i < a.count; i+=2 {
      let a1 = a[i]
      let a2 = a[i+1]
      println("\(a1)\(a2)")
    }
    

    Note that this does not check for uneven count of elements.

    0 讨论(0)
  • 2021-01-23 13:41

    Swift 4.1

    extension Array {
        /*
         [1,2,3,4,5].forEachSlice(2, { print($0) })
         => [1, 2]
         => [3, 4]
         => [5]
        */
        public func forEachSlice(_ n: Int, _ body: (ArraySlice<Element>) throws -> Void) rethrows {
            assert(n > 0, "n require to be greater than 0")
    
            for from in stride(from: self.startIndex, to: self.endIndex, by: n) {
                let to = Swift.min(from + n, self.endIndex)
                try body(self[from..<to])
            }
        }
    }
    
    0 讨论(0)
  • 2021-01-23 13:47

    As a small modification of the code from How to implement Haskell's splitEvery in Swift?, you could define an array extension

    extension Array {
        func eachSlice<S>(nInEach: Int, transform: [T] -> S) -> [S] {
            var result = [S]()
            for from in stride(from: 0, to: self.count, by: nInEach) {
                let to = advance(from, nInEach, self.count)
                result.append(transform(Array(self[from ..< to])))
            }
            return result
        }
    }
    

    and then use it as

    let arr = ["a", "b", "c", "d"]
    arr.eachSlice(2) { println("".join($0)) }
    

    Output:

    ab
    cd
    

    Another example:

    let iarr = [1, 2, 3, 4, 5, 6, 7]
    let sliceSums = iarr.eachSlice(3) {
        reduce($0, 0) { $0 + $1 } // sum of slice elements
    }
    println(sliceSums)
    // [6, 15, 7]
    

    Update for Swift 3:

    extension Array {
        func eachSlice<S>(_ nInEach: Int, transform: (ArraySlice<Element>) -> S) -> [S] {
            var result = [S]()
            var from = startIndex
            while from != endIndex {
                let to = indices.index(from, offsetBy: nInEach, limitedBy: endIndex) ?? endIndex
                result.append(transform(self[from ..< to]))
                from = to
            }
            return result
        }
    }
    
    let iarr = [1, 2, 3, 4, 5, 6, 7]
    let sliceSums = iarr.eachSlice(3) { $0.reduce(0, +) }
    print(sliceSums) // [6, 15, 7]
    
    0 讨论(0)
提交回复
热议问题