我在玩 swift 的Data
在下面的小代码中:
var d = Data(count: 10)
d[5] = 3
let d2 = d[5..<8]
print("\(d2[0])")
令我惊讶的是,这段代码抛出异常print()
而下面的代码则不然:
var d = Data(count: 10)
d[5] = 3
let d2 = d.subdata(in: 5..<8)
print("\(d2[0])")
我以某种方式理解为什么会发生这种情况,但我不明白为什么要这样设计。当我使用subdata()
我得到了范围的完整副本,因此索引从以下位置有效0
。但是当我使用范围订阅时[]
,我可以访问请求的范围,而索引与以前相同。所以在我的第一个例子中d2[5]
is 3
.
但我想知道为什么要这样设计呢?我不想使用以下方式复制我的数据subdata()
方法。我只是想通过更好的索引来访问部分数据。
如果将其传递给函数,这尤其会产生意想不到的行为。例如,以下代码会产生意外结果和异常,您可能不容易找出原因:
func testit(idata: Data) {
if idata.count > 0 {
print("\(idata.count)")
print("\(idata[0])")
}
}
//...
var d = Data(count: 10)
d[5] = 3
let d2 = d[5..<8]
testit(idata: d2)
这段代码确实很奇怪。因为如果你调试你的代码,你会看到print("\(idata.count)")
prints 3
作为大小idata
这是正确的,但是通过以下方式访问它idata[0]
创建异常。
这样的设计有什么道理吗?我期待我可以访问结果Data
from subscribe 从索引 0 开始,但事实并非如此。我可以在不使用的情况下执行此操作吗subdata()
它创建数据副本或使用附加参数来传递数据切片的基础?
d[5..<8]
回报Data.Slice
– 这恰好是Data
。一般来说,切片与其基本集合共享索引,如中所述Slice.
这种设计决策的一个可能原因是,它保证为切片添加下标是 O(1) 操作(添加一个offset访问基集合不一定是 O(1),例如不适用于字符串。)
这也很方便,如本示例中所示,在字符串中第二次出现字符之后定位文本:
let string = "abcdefgabcdefg"
// Find first occurrence of "d":
if let r1 = string.range(of: "d") {
// Find second occurrence of "d":
if let r2 = string[r1.upperBound...].range(of: "d") {
print(string[r2.upperBound...]) // efg
}
}
因此,您绝不能假设集合的索引是从零开始的(除非有记录,至于Array.startIndex). Use startIndex
获取第一个索引,或者first
获取第一个元素。
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)