Edited at

SwiftでRubyのeach_cons, each_sliceをする

Swift で、 Ruby の each_cons(n) みたいに、n個ずつずらしながら扱いたいときのTips。


コード

extension Array {

func eachPair() -> [(Element, Element)] {
return zip(self, self.dropFirst()).map({ ($0.0, $0.1) })
}

func eachCons(_ n: Int) -> [ArraySlice<Element>] {
return indices.dropLast(n-1).map({ self[$0...$0+n-1] })
}

func eachSlice(_ n: Int) -> [ArraySlice<Element>] {
return stride(from: 0, through: count - 1, by: n).map({ self[($0..<$0+n).clamped(to: indices)] })
}
}


使用

let sample = [1, 2, 3, 4, 5, 6]

sample.eachPair() // [(1, 2), (2, 3), (3, 4), (4, 5), (5, 6)]

sample.eachCons(3) // [[1, 2, 3], [2, 3, 4], [3, 4, 5], [4, 5, 6]]
sample.eachCons(6) // [[1, 2, 3, 4, 5, 6]]
sample.eachCons(7) // []

sample.eachSlice(2) // [[1, 2], [3, 4], [5, 6]]
sample.eachSlice(4) // [[1, 2, 3, 4], [5, 6]]
sample.eachSlice(7) // [[1, 2, 3, 4, 5, 6]]

eachPair はタプルで返るようになってます。

eachCons で大きい値を与えた場合、空の配列が返ります。


補足



  • eachCons(0) など0以下の値を与えるとエラーになるので、工夫しても良いかも。


  • eachPair() は、 Ruby で言う each_pair とは異なるので注意。

  • extension は Collection ではなく Array に対して書いています。 Dictionary などには使用しないので。


環境


  • Swift 5.0


参考