下面我正在尝试获取ArraySlice
draggignFan
的第i个元素。代码构建正常(没有警告),但程序在运行时在我试图像正常数组索引切片的行上死:
var draggingFan : ArraySlice<Card>?
...
if let draggingFan = draggingFan {
for i in 1 ..< draggingFan.count {
let card = draggingFan[i] // EXECUTION ERROR HERE
...
}
}
根据the docs,有first
和last
方法(我在别处使用没有问题)。那么如何在Swift中索引ArraySlice
? (注意:我故意跳过切片中的第0个索引 - 其他地方需要这样做。)
答案 0 :(得分:2)
您遇到此问题的原因是切片会保留您从中获取序列的原始索引号。因此,元素1不在此片中。
例如,请考虑以下代码:
let arr = [1,2,3,4,5,6,7,8,9]
let slice = arr[2...5]
现在什么是slice[1]
?它不是4
,即使这是切片中的第二件事。它是2
,因为切片仍然指向原始数组。换句话说,slice[1]
超出了切片的范围!这就是您遇到运行时错误的原因。
怎么办?那么,切片的实际索引是indices
。 那是你想要循环的东西。但是......你不希望切片指向的第一个元素。因此,您需要提升您要迭代的范围的startIndex
。因此:
if let draggingFan = draggingFan {
var ixs = draggingFan.indices
ixs.startIndex = ixs.startIndex.advancedBy(1)
for i in ixs {
// ... now your code will work ...
}
}
但是,在我看来,根本不需要对切片进行索引,你不应该这样做。您应该遍历切片本身,而不是通过其索引。你有这个:
for i in 1 ..< draggingFan.count
但这很像说
for aCard in draggingFan
...除了您要删除切片的第一个元素。然后放下它!这样说:
for aCard in draggingFan.dropFirst()
要知道这会有效,请在操场上试试:
let arr = [1,2,3,4,5,6,7,8,9]
let slice = arr[2...5]
for anInt in slice.dropFirst() {
print(anInt) // 4, 5, 6
}
正如您所看到的,我们正在循环使用所需的元素,而根本没有参考索引号。
答案 1 :(得分:2)
ArraySlice
的索引仍然与原始数组的索引相匹配。在您的情况下,您正在访问不在切片中的索引1
。如果您将索引偏移draggingFan.startIndex
,它将起作用:
if let draggingFan = draggingFan {
for i in 1 ..< draggingFan.count {
let card = draggingFan[draggingFan.startIndex + i]
...
}
}
可替换地:
if let draggingFan = draggingFan {
for i in draggingFan.startIndex + 1 ..< draggingFan.endIndex {
let card = draggingFan[i]
...
}
}
答案 2 :(得分:2)
这将访问切片中第二个元素到切片中最后一个元素的值:
ContentProvider
输出:
3,4,5,
答案 3 :(得分:1)
迭代切片中的元素: draggingFan?.forEach({(element) ... })
据我所知,获取一个特定元素,需要将其转换回数组,例如。
let draggingFanArray = Array(draggingFan!)
这里是我过去玩的游乐场代码,有各种各样的场景:
导入Cocoa
var a: Array<Int>?
var b: ArraySlice<Int>?
a = [1, 2, 3, 4, 5, 6, 7]
b = a![3...5]
let count = b!.count
b!.forEach({ (element) in
print("\(element)")
})
let c = Array(b!)
print(c[2])
编辑 ArraySlice扩展名:
extension ArraySlice {
func elementAtIndex(index: Int)->AnyObject?{
return Array(self)[index] as? AnyObject
}
}
答案 4 :(得分:1)
如果我有一个数组:
var arr = [1, 2, 3, 4, 5, 6, 7] // [1, 2, 3, 4, 5, 6, 7]
我拿了一个阵列:
let slice = arr[3..<arr.count] // [4, 5, 6, 7]
此切片的startIndex
为3,这意味着索引从3开始,到6结束。
现在,如果我想要一个包含除第一个元素之外的所有内容的切片,我可以使用dropFirst()
方法:
let sliceMinusFirst = slice.dropFirst() // [5, 6, 7]
此时,sliceMinusFirst
的{{1}}为4,这意味着我的索引范围为4到6。
现在,如果我想迭代这些以对项目做某事,我可以执行以下操作:
startIndex
或者,我可以使用for item in sliceMinusFirst {
print(item)
}
:
forEach
通过使用这些迭代形式,sliceMinusFirst.forEach { item in
print(item)
}
非零的事实并不重要,因为我不直接使用索引。并且它也不重要,在切片后,我想放弃第一项。我能够轻松地做到这一点。在我想要进行迭代时,我甚至可以做到这一点:
startIndex
这里我从原始切片中删除了第一个项目,没有创建任何中间变量。
请记住,如果您需要实际使用索引,那么您可能做错了什么。如果您确实需要索引,请确保您了解正在进行的操作。
此外,如果您想在切片后返回基于零的索引,则可以从切片创建一个数组:
slice.dropFirst().forEach { item in
print(item)
}