gpt4 book ai didi

Swift:如何使这个函数通用

转载 作者:行者123 更新时间:2023-11-30 13:45:40 24 4
gpt4 key购买 nike

这是我所拥有的:

class func truncateTailsOfRange(range: Range<Int>, portion: Double) -> Range<Int> {
let start = range.startIndex + Int(portion * Double(range.count))
let end = range.endIndex - Int(portion * Double(range.count))
return Range(start: start, end: end)
}

我想让这个通用的 IntegerType:

class func truncateTailsOfRange<T: IntegerType>(range: Range<T>, portion: Double) -> Range<T> {
let start = range.startIndex + T(portion * Double(range.count))
let end = range.endIndex - T(portion * Double(range.count))
return Range(start: start, end: end)
}

但是我得到的错误是:

Cannot invoke initializer for type Double with an argument list of type (T.Distance)

这可以做到吗?

最佳答案

首先您需要一个 CustomDoubleConvertible 协议(protocol)。这反射(reflect)了 CustomStringConvertible。您可以扩展所有想要转换为 Double 的类型。类似于返回类型的String表示形式的description

protocol CustomDoubleConvertible {

var doubleValue : Double { get }
}

extension Int : CustomDoubleConvertible {

var doubleValue : Double { return Double(self) }

}

extension Int16 : CustomDoubleConvertible {

var doubleValue : Double { return Double(self) }

}

如果您将该函数作为 Range 本身的扩展,您可以利用它的通用性质和它的 typealiases

extension Range where Element.Distance : CustomDoubleConvertible {

现在您可以像这样计算索引的偏移量:

let startOffset = Int(portion * self.count.doubleValue)
let endOffset = Int(portion * self.count.doubleValue)

如果您进一步限制 Range 使其 Element 必须是 Bi DirectionIndexType,您可以使用 successor前任

extension Range where Element.Distance : CustomDoubleConvertible, Element : BidirectionalIndexType {

这允许您通过迭代偏移量并调用successorpredecessor来获取完整的函数。

extension Range where Element.Distance : CustomDoubleConvertible, Element : BidirectionalIndexType {

func truncateTailsOfRange(portion: Double) -> Range<Element> {

let startOffset = Int(portion * self.count.doubleValue)
let endOffset = Int(portion * self.count.doubleValue)

var start = self.startIndex
var end = self.endIndex

for _ in 0..<startOffset { start = start.successor() }
for _ in 0..<endOffset { end = end.predecessor() }

return Range(start: start, end: end)
}
}

一些测试:

let rangeA = 1...4 // 1..<5

let rangeB = "a"..."g"

rangeA.truncateTailsOfRange(0.3) // 2..<4

rangeB.truncateTailsOfRange(0.3) // has no member ....



let w : Int16 = 3
let z : Int16 = 9

let rangeC = w...z // 3..<10
rangeC.truncateTailsOfRange(0.4) // 5..<8

关于Swift:如何使这个函数通用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34972949/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com