swift:修改字典中的数组

mal*_*lef 27 arrays syntax dictionary swift

如何轻松地将元素添加到字典中的数组?它总是抱怨could not find member 'append'could not find an overload for '+='

var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]

// all of these fail
dict["key"] += 4
dict["key"].append(4) // xcode suggests dict["key"].?.append(4) which also fails
dict["key"]!.append(4)
dict["key"]?.append(4)

// however, I can do this:
var arr = dict["key"]!
arr.append(4) // this alone doesn't affect dict because it's a value type (and was copied)
dict["key"] = arr
Run Code Online (Sandbox Code Playgroud)

如果我只是将数组分配给var,修改它然后重新分配给dict,我不会复制所有内容吗?这不会有效也不优雅.

Nat*_*ook 32

Swift beta 5添加了这个功能,你已经在几次尝试中确定了新方法.的解缠运营商!?现在穿过值要么运营商或方法调用.也就是说,您可以通过以下任何方式添加到该数组:

dict["key"]! += [4]
dict["key"]!.append(4)
dict["key"]?.append(4)
Run Code Online (Sandbox Code Playgroud)

与往常一样,请注意您使用的操作符 - 强制解包字典中不存在的值会给您带来运行时错误:

dict["no-key"]! += [5]        // CRASH!
Run Code Online (Sandbox Code Playgroud)

而使用可选链接将无声地失败:

dict["no-key"]?.append(5)     // Did it work? Swift won't tell you...
Run Code Online (Sandbox Code Playgroud)

理想情况下,您可以使用新的空合并运算符??来解决第二种情况,但是现在它无法正常工作.


来自Swift beta 5之前的答案:

这是斯威夫特的一个怪癖,你不可能做你想做的事情.问题是任何Optional变量的实际上都是常量 - 即使强行解包也是如此.如果我们只定义一个Optional数组,那么我们可以做什么,不能做什么:

var arr: Array<Int>? = [1, 2, 3]
arr[0] = 5
// doesn't work: you can't subscript an optional variable
arr![0] = 5
// doesn't work: constant arrays don't allow changing contents
arr += 4
// doesn't work: you can't append to an optional variable
arr! += 4
arr!.append(4)
// these don't work: constant arrays can't have their length changed
Run Code Online (Sandbox Code Playgroud)

你在使用字典时遇到问题的原因是,下载字典会返回一个Optional值,因为不能保证字典会有该键.因此,字典中的数组与Optional数组具有相同的行为,如上所示:

var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
dict["key"][0] = 5         // doesn't work
dict["key"]![0] = 5        // doesn't work
dict["key"] += 4           // uh uh
dict["key"]! += 4          // still no
dict["key"]!.append(4)     // nope
Run Code Online (Sandbox Code Playgroud)

如果你需要在字典中更改数组中的某些内容,则需要获取数组的副本,更改它并重新分配,如下所示:

if var arr = dict["key"] {
    arr.append(4)
    dict["key"] = arr
}
Run Code Online (Sandbox Code Playgroud)

ETA:相同的技术在Swift beta 3中有效,尽管常量数组不再允许更改内容.

  • 我很快就会给你一个绿色的嘀嗒声.真的,Apple?我希望如果他们不重新设计这种语言,他们至少会为这种情况制作一种新的语言结构.无论如何:我只是尝试了`dict ["key"] = dict ["key"]!.追加(4)在操场上的位,我仍然得到'找不到成员'追加'错误.是什么赋予了? (3认同)

Wer*_*her 12

接受的答案绕过了以下更简单的可能性,这也适用于较旧的 Swift 版本:

var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]

print(dict)

dict["key", default: [Int]()].append(4)

print(dict)
Run Code Online (Sandbox Code Playgroud)

这将打印:

["key": [1, 2, 3]]
["key": [1, 2, 3, 4]]
Run Code Online (Sandbox Code Playgroud)

和这个:

var dict = Dictionary<String, Array<Int>>()
dict["key", default: [Int]()].append(4)
print(dict)
Run Code Online (Sandbox Code Playgroud)

将打印:

["key": [4]]
Run Code Online (Sandbox Code Playgroud)


gui*_*dos 6

作为一个简单的解决方法,您可以使用NSMutableArray:

import Foundation

var dict = Dictionary<String, NSMutableArray>()
dict["key"] = [1, 2, 3] as NSMutableArray
dict["key"]!.addObject(4)
Run Code Online (Sandbox Code Playgroud)

我在我的项目中使用了这么简单的解决方案:

https://github.com/gui-dos/Guigna/blob/5c02f7e70c8ee3b2265f6916c6cbbe5cd3963fb5/Guigna-Swift/Guigna/GuignaAppDelegate.swift#L1150-L1157

  • 这是正确的,因为`NSMutableArray`是一个类,不像Swift的原生数组,它被定义为结构.在这个实现中``dict ["key"]!`仍然是不可变的,但这并不重要,因为你可以改变不可变类的底层属性. (3认同)
  • 它确实有效,是一种非常简单明智的解决方法.我已经开始梦想NS*无代码,但是:( (3认同)