如何从Swift ArraySlice中获取第i个元素?

时间:2016-04-06 17:07:41

标签: arrays swift slice

下面我正在尝试获取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,有firstlast方法(我在别处使用没有问题)。那么如何在Swift中索引ArraySlice(注意:我故意跳过切片中的第0个索引 - 其他地方需要这样做。)

5 个答案:

答案 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)
}