问题描述
问题
let x = (0..<10).splitEvery( 3 )
XCTAssertEqual( x, [(0...2),(3...5),(6...8),(9)], "implementation broken" )
评论
我在计算范围中的元素数量时遇到问题,等等...
I am running into problems calculating number of elements in the Range, etc...
extension Range
{
func splitEvery( nInEach: Int ) -> [Range]
{
let n = self.endIndex - self.startIndex // ERROR - cannot invoke '-' with an argument list of type (T,T)
}
}
推荐答案
一个范围内的值都是ForwardIndexType
,所以你只能advance()
他们,或计算distance()
,但没有定义减法-
.预付款金额必须是相应的输入 T.Distance
.所以这将是一个可能的实现:
The values in a range are of ForwardIndexType
, so you can only advance()
them,or compute the distance()
, but the subtraction -
is not defined. The advance amount has to be of the correspondingtype T.Distance
. So this would be a possible implementation:
extension Range {
func splitEvery(nInEach: T.Distance) -> [Range] {
var result = [Range]() // Start with empty array
var from = self.startIndex
while from != self.endIndex {
// Advance position, but not beyond the end index:
let to = advance(from, nInEach, self.endIndex)
result.append(from ..< to)
// Continue with next interval:
from = to
}
return result
}
}
示例:
println( (0 ..< 10).splitEvery(3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
但是请注意 0 .. 不是整数列表(或数组).要将 array 拆分为子数组,您可以定义类似的扩展:
Note however that 0 ..< 10
is not a list (or array) of integers. To split an array into subarrays you could define a similar extension:
extension Array {
func splitEvery(nInEach: Int) -> [[T]] {
var result = [[T]]()
for from in stride(from: 0, to: self.count, by: nInEach) {
let to = advance(from, nInEach, self.count)
result.append(Array(self[from ..< to]))
}
return result
}
}
示例:
println( [1, 1, 2, 3, 5, 8, 13].splitEvery(3) )
// Output: [[1, 1, 2], [3, 5, 8], [13]]
更通用的方法可能是拆分所有sliceable 对象.但是 Sliceable
是协议,协议不能扩展.你可以做的是定义一个函数,将切片对象作为第一个参数:
A more general approach could be to split all sliceable objects. But Sliceable
is protocol and protocols cannot be extended. What you can do instead is todefine a function that takes the sliceable object as the first argument:
func splitEvery<S : Sliceable>(seq : S, nInEach : S.Index.Distance) -> [S.SubSlice] {
var result : [S.SubSlice] = []
var from = seq.startIndex
while from != seq.endIndex {
let to = advance(from, nInEach, seq.endIndex)
result.append(seq[from ..< to])
from = to
}
return result
}
(注意这个函数与(扩展)方法完全无关以上定义.)
(Note that this function is completely unrelated to the (extension) methodsdefined above.)
示例:
println( splitEvery("abcdefg", 2) )
// Output: [ab, cd, ef, g]
println( splitEvery([3.1, 4.1, 5.9, 2.6, 5.3], 2) )
// Output: [[3.1, 4.1], [5.9, 2.6], [5.3]]
范围不可切片,但您可以定义一个单独的函数范围参数:
Ranges are not sliceable, but you could define a separate function that takes arange argument:
func splitEvery<T>(range : Range<T>, nInEach : T.Distance) -> [Range<T>] {
var result : [Range<T>] = []
var from = range.startIndex
while from != range.endIndex {
let to = advance(from, nInEach, range.endIndex)
result.append(from ..< to)
from = to
}
return result
}
示例:
println( splitEvery(0 ..< 10, 3) )
// Output: [0..<3, 3..<6, 6..<9, 9..<10]
这篇关于如何在 Swift 中实现 Haskell 的 splitEvery?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!