endIndex返回与count相同的值。这是一个正确的行为还是一个错误?
var ar = [1, 2, 3, 4] ar.count // 4 ar.endIndex // 4
7hiiyaii1#
count是集合中的项数,而endIndex是刚过集合末尾的Index (from the Collection protocol)。对于Array,它们是相同的。对于其他一些集合,如ArraySlice,它们不是:
count
endIndex
Index
Collection
Array
ArraySlice
let array = ["a", "b", "c", "d", "e"] array.startIndex // 0 array.count // 5 array.endIndex // 5 let slice = array[1..<4] // elements are "b", "c", "d" slice.startIndex // 1 slice.count // 3 slice.endIndex // 4
olmpazwi2#
Array.endIndex是指数组末尾后的1(或与count相同),用于迭代目的,而不是下标。
Array.endIndex
let x = [1, 2, 3, 4] for var i = x.startIndex; i < x.endIndex; i++ { println(x[i]) }
bqjvbblv3#
这里似乎有很多评论说endIndex是start之后的count元素是违反直觉的。我不能说对一个人或另一个人来说什么是直觉的,但这不是随机的。这是一个非常明智的工作方式。我相信有些人会想到这样的索引,索引直接指向包含值的“框”:
start
|-----|-----|-----|-----| | 0 | 1 | 2 | 3 | |-----|-----|-----|-----| ↑ ↑ start end
但这并不是正确的思考方式,正确的方式是这样的,索引指向你开始阅读值的边界:
如果一个人从起点开始,向前推进count倍,他应该期望到达终点,这就是它所达到的目的。现在考虑空列表的情况:
| | ↑ start ↑ end
所有的事情都和预期的一样。如果你从start开始,并前进0个元素,你会到达end。我在这里故意说“前进”。索引不一定是整数。它们只需要有一个“前进”操作和一个结束。如果endIndex是“最后一个元素的索引”,那么对于一个空列表,它是什么呢?没有最后一个元素。当索引是有符号整数时,将它设置为-1是一种可能的回避,但是Swift根本不要求Collection索引是整数(事实上,它们通常不是;数组是非常不寻常的)。Swift可以使endIndex可选,但这使数学更加丑陋。正如HangarRash在评论中指出的,对于Int索引不从零开始的集合(特别是ArraySlice和切片Data),endIndex在任何情况下都不会是count - 1,对于空切片,即使偏移startIndex + count - 1也不会是-1(所以你不能只检查-1来表示“空”),并且可以指向包含它的Array,这显然是错误的。规则endIndex = startIndex + count和“空集合具有startIndex == endIndex”对于切片仍然同样地起作用。这种方法在各种情况下是一致的,而不需要变通方法。从起点到终点的距离应该是计数(而不是比count少一),long早于Swift,并且与许多语言从零开始而不是从1开始对数组进行编号的原因密切相关。(“上述边界之间的差异等于子序列的长度”)看起来违反直觉(有时候我确实觉得很惊讶!),这种方法非常强大。它不是关于性能或“C使用指针”或类似的东西。而是因为它使算法更漂亮。
end
count - 1
startIndex + count - 1
endIndex = startIndex + count
3条答案
按热度按时间7hiiyaii1#
count
是集合中的项数,而endIndex
是刚过集合末尾的Index
(from theCollection
protocol)。对于
Array
,它们是相同的。对于其他一些集合,如ArraySlice
,它们不是:olmpazwi2#
Array.endIndex
是指数组末尾后的1(或与count相同),用于迭代目的,而不是下标。bqjvbblv3#
这里似乎有很多评论说
endIndex
是start
之后的count
元素是违反直觉的。我不能说对一个人或另一个人来说什么是直觉的,但这不是随机的。这是一个非常明智的工作方式。我相信有些人会想到这样的索引,索引直接指向包含值的“框”:
但这并不是正确的思考方式,正确的方式是这样的,索引指向你开始阅读值的边界:
如果一个人从起点开始,向前推进
count
倍,他应该期望到达终点,这就是它所达到的目的。现在考虑空列表的情况:
所有的事情都和预期的一样。如果你从
start
开始,并前进0个元素,你会到达end
。我在这里故意说“前进”。索引不一定是整数。它们只需要有一个“前进”操作和一个结束。如果
endIndex
是“最后一个元素的索引”,那么对于一个空列表,它是什么呢?没有最后一个元素。当索引是有符号整数时,将它设置为-1是一种可能的回避,但是Swift根本不要求Collection索引是整数(事实上,它们通常不是;数组是非常不寻常的)。Swift可以使endIndex
可选,但这使数学更加丑陋。正如HangarRash在评论中指出的,对于Int索引不从零开始的集合(特别是ArraySlice和切片Data),
endIndex
在任何情况下都不会是count - 1
,对于空切片,即使偏移startIndex + count - 1
也不会是-1(所以你不能只检查-1来表示“空”),并且可以指向包含它的Array,这显然是错误的。规则endIndex = startIndex + count
和“空集合具有startIndex == endIndex”对于切片仍然同样地起作用。这种方法在各种情况下是一致的,而不需要变通方法。从起点到终点的距离应该是计数(而不是比count少一),long早于Swift,并且与许多语言从零开始而不是从1开始对数组进行编号的原因密切相关。(“上述边界之间的差异等于子序列的长度”)看起来违反直觉(有时候我确实觉得很惊讶!),这种方法非常强大。它不是关于性能或“C使用指针”或类似的东西。而是因为它使算法更漂亮。