Swift相当于each_slice

时间:2015-01-16 13:22:07

标签: swift

在Swift中有类似Ruby的可枚举#each_slice吗?

Ruby示例:

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

输出:

ab
cd

3 个答案:

答案 0 :(得分:5)

作为How to implement Haskell's splitEvery in Swift?代码的一个小修改,您可以定义数组扩展

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

然后将其用作

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

输出:

ab
cd

另一个例子:

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]

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]

答案 1 :(得分:1)

修改我的评论:

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

请注意,这不会检查元素的不均匀计数。

答案 2 :(得分:0)

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