SWIFT 中的元组数组作为函数的参数
Tuple array in SWIFT as a parameter of function
我需要将元组数组作为参数传递给从数组中选择随机元组的函数,同时考虑两个其他参数)这个函数 returns 索引,然后我将使用它来播放这个随机文件。而这个函数在class 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
}
}
但是当我通过这样做从另一个 class 调用函数时。
indexToPlay = Int(fileManager().randomizeTheNextInstrument(fileManager().drums, Strength: drumStrength, KeyNote: "C"))
它给我致命错误:“数组索引超出范围
(lldb)” 它告诉我数组 instrumentArrayInput 有 5 个值,但值为 'none',instrumentArray 有 3 个值,但值为 'none'。接下来看起来很奇怪的是 indexToChoose = 140734791422096。而且它还写了我 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, sub code=0x0) 的字符串:
if instrumentArray[index].4 == true {
我做错了什么?
这个:
for index in 0...instrumentArray.count {
应该是:
for index in 0..<instrumentArray.count {
由于数组是零索引的,因此最后一个有效索引比数组中的项目数少一。
Anthony 实际上指出了您的函数的其他几个问题,所有这些问题都可以通过使用内置的过滤器函数来解决:
instrumentArray = instrumentArrayInput.filter {
return ![=12=].4 && [=12=].6 == KeyNote && [=12=].3 == Strength
}
替换整个 for 循环。
为了解决更多的问题,我会选择这样的方法,尽管有更多的更改需要推荐(比如使用结构或 class 而不是元组):
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 ![=13=].4 && [=13=].6 == KeyNote && [=13=].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
}
在循环中,您正在从数组中删除元素,因此它的长度减少了。
而且,有3个独立的if
语句,可以导致在同一次迭代中最多移除3个元素。我会在每个 if
主体中添加一个 break
(以跳过当前迭代并移动到下一个),或者将它们重新组织为 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)
}
}
需要倒序循环,因为当一个元素被移除时,它之后的所有元素都会向后移动一个位置,而它之前的所有元素都不会受到影响。这样您就可以确保所有仍待处理的元素的索引都不会更改。
我需要将元组数组作为参数传递给从数组中选择随机元组的函数,同时考虑两个其他参数)这个函数 returns 索引,然后我将使用它来播放这个随机文件。而这个函数在class 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
}
}
但是当我通过这样做从另一个 class 调用函数时。
indexToPlay = Int(fileManager().randomizeTheNextInstrument(fileManager().drums, Strength: drumStrength, KeyNote: "C"))
它给我致命错误:“数组索引超出范围 (lldb)” 它告诉我数组 instrumentArrayInput 有 5 个值,但值为 'none',instrumentArray 有 3 个值,但值为 'none'。接下来看起来很奇怪的是 indexToChoose = 140734791422096。而且它还写了我 EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, sub code=0x0) 的字符串:
if instrumentArray[index].4 == true {
我做错了什么?
这个:
for index in 0...instrumentArray.count {
应该是:
for index in 0..<instrumentArray.count {
由于数组是零索引的,因此最后一个有效索引比数组中的项目数少一。
Anthony 实际上指出了您的函数的其他几个问题,所有这些问题都可以通过使用内置的过滤器函数来解决:
instrumentArray = instrumentArrayInput.filter {
return ![=12=].4 && [=12=].6 == KeyNote && [=12=].3 == Strength
}
替换整个 for 循环。
为了解决更多的问题,我会选择这样的方法,尽管有更多的更改需要推荐(比如使用结构或 class 而不是元组):
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 ![=13=].4 && [=13=].6 == KeyNote && [=13=].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
}
在循环中,您正在从数组中删除元素,因此它的长度减少了。
而且,有3个独立的if
语句,可以导致在同一次迭代中最多移除3个元素。我会在每个 if
主体中添加一个 break
(以跳过当前迭代并移动到下一个),或者将它们重新组织为 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)
}
}
需要倒序循环,因为当一个元素被移除时,它之后的所有元素都会向后移动一个位置,而它之前的所有元素都不会受到影响。这样您就可以确保所有仍待处理的元素的索引都不会更改。