为什么 Data.endIndex 和 Data.count 不同?

Rya*_*yan 3 swift

let str = "This is a swift bug"\nlet data = Data(str.utf8)\nprint("data size = ", data.endIndex, data.count)\n\nlet trimmed = data[2..<data.endIndex]\nprint("trimmed size = ", trimmed.endIndex, trimmed.count)\n
Run Code Online (Sandbox Code Playgroud)\n

结果是

\n
data size =  19 19\ntrimmed size =  19 17\n
Run Code Online (Sandbox Code Playgroud)\n

根据苹果文档endIndex

\n
This is the \xe2\x80\x9cone-past-the-end\xe2\x80\x9d position, and will always be equal to the count.\n
Run Code Online (Sandbox Code Playgroud)\n

这是一个错误吗?或者我错过了什么?

\n

Rob*_*ier 6

您应该打开 Apple 反馈以获取Data.endIndex. 这是不正确的。

数据的 startIndex 不承诺为零,这是一个不为零的示例。不幸的是,在 Data 上使用 Int 下标非常危险,除非您确切地知道 Data 是如何构造的(特别是它的索引为零)。

数据独特地混合了两个事实,这使得正确使用变得棘手:

  • 这是它自己的切片
  • 它的索引是 Int

有关对此的一些讨论以及建议的模式,请参阅Data.popFirst()、removeFirst() 调整索引。另请参阅数据范围订阅此问题的另一个版本的奇怪行为


mat*_*att 5

array[2..<array.endIndex]当您使用类似于创建切片的表达式时。切片是数组(或类似于数组的东西)的一种窗口。它startIndex不一定是原始索引的最后一个索引之后的索引0endIndex

\n

例子:

\n
let arr = Array(1...10)\nprint(arr.startIndex) // 0\nprint(arr.endIndex) // 10\nlet slice = arr[2...4]\nprint(slice.startIndex) // 2\nprint(slice.endIndex) // 5\nprint(slice.count) // 3\n
Run Code Online (Sandbox Code Playgroud)\n

你明白这是如何运作的吗?切片有自己的逻辑。它的大小(计数)是切片的大小,但它的索引号来自原始数组,因为切片只不过是指向原始数组的一部分的指针。它没有独立的存在;可以说,这只是一种观察方式。

\n

一个重要的后果是会崩溃:正如我们已经被告知的,slice[0]第一个可用索引是 2。slice这就是为什么知道您正在处理原始数组还是切片至关重要。

\n

但是,至少您有理由知道这个问题可能存在,因为slice有一个特殊类型 \xe2\x80\x94 Array<Int>.SubSequence,意味着 ArraySlice 。但是,您通过数据遇到这种情况的事实使其变得更加棘手,因为它trimmed是作为数据键入的,而不是作为 DataSlice 键入的!它实际上Data.SubSequencea ,但是您没有简单的方法可以找到它!那是因为Data.SubSequence对数据本身进行了类型别名。这被视为数据实现中的缺陷。

\n

然而,这是完全相同的现象。这些答案看起来应该很熟悉:

\n
let str = "This is a swift bug"\nlet data = Data(str.utf8)\nlet trimmed = data[2...4]\nprint(trimmed.startIndex) // 2\nprint(trimmed.endIndex) // 5\nprint(trimmed.count) // 3\n
Run Code Online (Sandbox Code Playgroud)\n

解决这个问题的最好方法是“不要这样做”。要将数据的子范围作为真实数据,请使用subdata

\n
let trimmed2 = data.subdata(in: 2..<5)\nprint(trimmed2.startIndex) // 0, and so on; it's an independent copy\n
Run Code Online (Sandbox Code Playgroud)\n

  • @aheze 实际上我只是说 Rob Napier 所说的。他说得更简洁了!这个问题的核心可以用他的一句话来概括:“数据就是它自己的切片”。我只是解释这意味着什么。:) (2认同)