SWIFT中的元组数组作为函数的参数

时间:2015-02-05 21:05:51

标签: ios arrays xcode swift tuples

我需要传递元组数组作为一个函数的参数,该函数从数组中选择随机元组,同时考虑另外两个参数。)此函数返回索引,我将使用该索引来播放此随机文件。此函数位于类fileManager()

class fileManager  {
    var drums = [
        ("drum", "drum", 8, 2, false, 153, "C", 1),
        ("drum", "drum2", 6, 3, false, 153, "C", 1),
        ("drum", "drum3", 8, 2, false, 153, "C", 1),
        ("drum", "drum4", 4, 2, false, 153, "C", 1),
        ("drum", "drum5", 8, 1, false, 153, "C", 1)  ]

    var piano = [
        ("piano", "piano", 8, 2, false, 153, "C", 1),
        ("piano", "piano2", 8, 3, false, 153, "C", 1),
        ("piano", "piano3", 8, 1, false, 153, "C", 1)
    ]

    //instrumentArray will be any instrument, Strength - we need to find, KeyNote - we need to find in Array.

    func randomizeTheNextInstrument (instrumentArrayInput: [(String,String,Int,Int,Bool,Int,String, Int)], Strength: Int , KeyNote: String) -> Int {
        var instrumentArray = instrumentArrayInput
        var indexInstrument: Int!
        for index in 0...instrumentArray.count {
            if instrumentArray[index].4 == true { //check if played
                instrumentArray.removeAtIndex(index)
            }
            if instrumentArray[index].6 != KeyNote { // check keyNote
                instrumentArray.removeAtIndex(index)
            }
            if instrumentArray[index].3 != Strength { // check strength
                instrumentArray.removeAtIndex(index)
            }
        }

        var indexToChoose: Int = Int(arc4random_uniform(UInt32(instrumentArray.count)))
        for index in 0...instrumentArrayInput.count {
            if instrumentArrayInput[index].1 == instrumentArray[indexToChoose].1 { // finds what one in ArrayInpu equals the randomized one in Array that chosen
                indexInstrument = index
            }
        }
        return indexInstrument
    }
}

但是当我通过这样做从另一个类调用该函数时。

indexToPlay = Int(fileManager().randomizeTheNextInstrument(fileManager().drums, Strength: drumStrength, KeyNote: "C"))

它给了我致命的错误:“数组索引超出范围 (lldb)“它告诉我数组instrumentArrayInput有5个值,但值是'none',instrumentArray有3个值,但值是'none'。接下来,看起来很奇怪的是indexToChoose = 140734791422096。它还写道我的字符串EXC_BAD_INSTRUCTION(代码= EXC_I386_INVOP,子代码= 0x0):

if instrumentArray[index].4 == true { 

我做错了什么?

2 个答案:

答案 0 :(得分:0)

此:

for index in 0...instrumentArray.count {

应该是:

for index in 0..<instrumentArray.count {

由于数组是零索引的,因此最后一个有效索引比数组中的项数少一个。

Anthony实际上指出了你的函数的几个问题,所有这些问题都可以通过使用内置的过滤器函数来解决:

instrumentArray = instrumentArrayInput.filter {
    return !$0.4 && $0.6 == KeyNote && $0.3 == Strength
}

替换整个for循环。

为了解决更多问题,我会选择这样的东西,虽然有更多建议改变(比如使用结构或类而不是元组):

class FileManager  {
    typealias Instrument = (String,String,Int,Int,Bool,Int,String, Int)

    var drums : [Instrument] = [
        ("drum", "drum", 8, 2, false, 153, "C", 1),
        ("drum", "drum2", 6, 3, false, 153, "C", 1),
        ("drum", "drum3", 8, 2, false, 153, "C", 1),
        ("drum", "drum4", 4, 2, false, 153, "C", 1),
        ("drum", "drum5", 8, 1, false, 153, "C", 1)  
    ]

    var piano : [Instrument] = [
        ("piano", "piano", 8, 2, false, 153, "C", 1),
        ("piano", "piano2", 8, 3, false, 153, "C", 1),
        ("piano", "piano3", 8, 1, false, 153, "C", 1)
    ]

    func randomizeTheNextInstrument(instrumentArrayInput: [Instrument], Strength: Int, KeyNote: String) -> Int? {
        let instrumentArray = instrumentArrayInput.filter {
            return !$0.4 && $0.6 == KeyNote && $0.3 == Strength
        }

        if instrumentArray.count <= 0 {
            return nil
        }

        let indexToChoose: Int = Int(arc4random_uniform(UInt32(instrumentArray.count - 1)))
        let name = instrumentArray[indexToChoose].1

        for index in 0 ..< instrumentArrayInput.count {
            if name == instrumentArrayInput[index].1 {
                return index
            }
        }

        return nil
    }
}

let fileManager = FileManager()

if let indexToPlay = fileManager.randomizeTheNextInstrument(fileManager.drums, Strength: 3, KeyNote: "C") {
    println("\(fileManager.drums[indexToPlay])")
    fileManager.drums[indexToPlay].4 = true
}

if let indexToPlay = fileManager.randomizeTheNextInstrument(fileManager.drums, Strength: 3, KeyNote: "C") {
    println("\(fileManager.drums[indexToPlay])")
    fileManager.drums[indexToPlay].4 = true
}

答案 1 :(得分:0)

在循环中,您要从数组中删除元素,因此其长度会减小。 此外,还有3个独立的if语句,这些语句最多可以在同一次迭代中删除3个元素。我会在每个break正文中添加if(跳过当前的迭代并移到下一个),或者将它们重新组织为if/else if/else

但是为了修复异常,我建议添加元素以保留在第二个数组中,或者仅仅是它们的索引,而不是从数组中删除元素。

最后,请注意循环错误,应该是for index in 0..<instrumentArray.count而不是for index in 0...instrumentArray.count


<强>更新

如果你仍然需要保留从数组中删除元素的最初想法,那么你应该修改循环以反向顺序遍历它,并使用if/elseif而不是独立的if。例如:

for var index = instrumentArray.count - 1; index >= 0; --index {
    if instrumentArray[index].4 == true { //check if played
        instrumentArray.removeAtIndex(index)
    } else if instrumentArray[index].6 != KeyNote { // check keyNote
        instrumentArray.removeAtIndex(index)
    } else if instrumentArray[index].3 != Strength { // check strength
        instrumentArray.removeAtIndex(index)
    }
}

需要以相反的顺序循环,因为当一个元素被移除时,它后面的所有元素都会向后移动一个位置,而前面的所有元素都不会受到影响。通过这种方式,您可以确保所有仍处理的元素都不会更改其索引。