Swift 数组字典
Swift Dictionary of Arrays
我正在制作一个具有不同游戏模式的应用程序,每个游戏模式都有一些分数。我试图将所有分数存储在数组字典中,其中字典的键是游戏的 id(字符串),关联的数组包含该游戏模式的分数列表。但是当我尝试将数组的值初始化为随机值时,Swift 中断,出现以下错误。这段代码将在操场上中断。我做错了什么?
let modes = ["mode1", "mode2", "mode3"]
var dict = Dictionary<String, [Int]>()
for mode in modes
{
dict[mode] = Array<Int>()
for j in 1...5
{
dict[mode]?.append(j)
let array:[Int] = dict[mode]!
let value:Int = array[j] //breaks here
}
}
错误:
Execution was interrupted, reason: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0).
你的问题是数组下标是从零开始的。所以当你写:
var a: [Int] = []
for i in 1...5 {
a.append(42)
println(a[i])
}
你会得到一个运行时错误,因为第一次循环你在下标 a[1]
时只有一个 a[0]
。在您的代码中,您需要执行 for j in 0..<5
或 let value = array[j-1]
.
顺便说一句,尽管 dict[mode]!
是绝对安全的(因为您刚刚添加了它),但最好避免这种习惯,因为有一天您的代码不会像您想象的那样正确,然后 !
会在你的脸上爆炸。 几乎总有一种更好的方式来写你想要的东西而不需要!
。
此外,一般来说,每当您使用数组下标时,您都会冒着因意外处理此处这样的越界索引而导致意外搞砸的风险。有很多选择意味着实际上使用 a[i]
很容易避免:
如果您想要集合的索引(如数组),而不是:
for i in 0..<a.count { }
你可以写
for i in indices(a) { }
如果要对数组中的元素进行编号,而不是
for i in indices(a) { println("item \(i) is \(a[i])" }
你可以写
for (i, elem) in enumerate(a) { println("item \(i) is \(elem)") }
如果集合恰好有一个Int
作为索引(比如Array
),你可以使用i
作为索引,但是如果没有(比如作为 String
) 获取索引和元素的替代方法是:
let s = "hello"
for (idx, char) in Zip2(indices(s),s) { }
如果您想要数组的第一个或最后一个元素,而不是:
if a.count > 0 { let x = a[0] }
if a.count > 0 { let x = a[a.count - 1] }
你可以写
if let first = a.first { let x = first }
if let last = a.last { let x = first }
一般情况下,map
、filter
和 reduce
优于 for 循环(但不要执着于此,有时 for 循环更好)
我正在制作一个具有不同游戏模式的应用程序,每个游戏模式都有一些分数。我试图将所有分数存储在数组字典中,其中字典的键是游戏的 id(字符串),关联的数组包含该游戏模式的分数列表。但是当我尝试将数组的值初始化为随机值时,Swift 中断,出现以下错误。这段代码将在操场上中断。我做错了什么?
let modes = ["mode1", "mode2", "mode3"]
var dict = Dictionary<String, [Int]>()
for mode in modes
{
dict[mode] = Array<Int>()
for j in 1...5
{
dict[mode]?.append(j)
let array:[Int] = dict[mode]!
let value:Int = array[j] //breaks here
}
}
错误:
Execution was interrupted, reason: EXC_BAD_INSTRUCTION(code=EXC_I386_INVOP, subcode=0x0).
你的问题是数组下标是从零开始的。所以当你写:
var a: [Int] = []
for i in 1...5 {
a.append(42)
println(a[i])
}
你会得到一个运行时错误,因为第一次循环你在下标 a[1]
时只有一个 a[0]
。在您的代码中,您需要执行 for j in 0..<5
或 let value = array[j-1]
.
顺便说一句,尽管 dict[mode]!
是绝对安全的(因为您刚刚添加了它),但最好避免这种习惯,因为有一天您的代码不会像您想象的那样正确,然后 !
会在你的脸上爆炸。 几乎总有一种更好的方式来写你想要的东西而不需要!
。
此外,一般来说,每当您使用数组下标时,您都会冒着因意外处理此处这样的越界索引而导致意外搞砸的风险。有很多选择意味着实际上使用 a[i]
很容易避免:
如果您想要集合的索引(如数组),而不是:
for i in 0..<a.count { }
你可以写
for i in indices(a) { }
如果要对数组中的元素进行编号,而不是
for i in indices(a) { println("item \(i) is \(a[i])" }
你可以写
for (i, elem) in enumerate(a) { println("item \(i) is \(elem)") }
如果集合恰好有一个
Int
作为索引(比如Array
),你可以使用i
作为索引,但是如果没有(比如作为String
) 获取索引和元素的替代方法是:let s = "hello" for (idx, char) in Zip2(indices(s),s) { }
如果您想要数组的第一个或最后一个元素,而不是:
if a.count > 0 { let x = a[0] } if a.count > 0 { let x = a[a.count - 1] }
你可以写
if let first = a.first { let x = first } if let last = a.last { let x = first }
一般情况下,
map
、filter
和reduce
优于 for 循环(但不要执着于此,有时 for 循环更好)