美文网首页
Collection 安全取值

Collection 安全取值

作者: 游城十代2dai | 来源:发表于2022-12-20 10:46 被阅读0次

需求:

对于数组或者 Data 等类型需要做一个类似切割的操作, 比如 123456, 想要在没两个字符后面添加 “:”, 结果是 12:34:56

方案有很多办法, 肯定是依赖 while 或者 for

现在通过系统的两个方法实现安全取值, 此方式比 sub 截取子段安全

一个是 prefix, 另一个是 dropFirst

prefix: 效果是获取从开始位置起固定长度的子段

dropFirst: 效果是获取从固定长度起到结束位置的子段


var data: String = "123456"

var result: String = ""

let interval: Int = 2

while data.isEmpty == false {

 let prefix = data.prefix(interval)

 let drop = data.dropFirst(interval)

 result.append(contentsOf: prefix)

 if drop.isEmpty == false {

 result.append(contentsOf: ":")

 }

 data = String(drop)

}

print("data: \(data), result: \(result)")

通过 Collection 源码 可以知道 prefix 和 dropFirst 都是调用


func index(

 _ i: Index, offsetBy distance: Int, limitedBy limit: Index

 ) -> Index?

prefix 和 dropFirst 源码:


@inlinable

 public __consuming func prefix(_ maxLength: Int) -> SubSequence {

 _precondition(

 maxLength >= 0,

 "Can't take a prefix of negative length from a collection")

 let end = index(startIndex,

 offsetBy: maxLength, limitedBy: endIndex) ?? endIndex

 return self[startIndex..<end]

 }

@inlinable

 public __consuming func dropFirst(_ k: Int = 1) -> SubSequence {

 _precondition(k >= 0, "Can't drop a negative number of elements from a collection")

 let start = index(startIndex, offsetBy: k, limitedBy: endIndex) ?? endIndex

 return self[start..<endIndex]

 }

offsetBy:limitedBy: 方法源码中实际调用了 for 循环, 所以单独调用 prefix 和 dropFirst 就是两次 for, 为了满足需求并减少 for 可以自己模仿源码实现, 如图

最后把这一步可以抽成一个扩展:


extension Collection {

 func split(maxLength: Int) -> (prefix: SubSequence, drop: SubSequence) {

 let index = index(startIndex, offsetBy: maxLength, limitedBy: endIndex) ?? endIndex

 return (self[startIndex..<index], self[index..<endIndex])

 }

}

该方式的优点就是很安全不会crash

相关文章

网友评论

      本文标题:Collection 安全取值

      本文链接:https://www.haomeiwen.com/subject/epeyqdtx.html