Swift 1D 字典到 2D

Posted

技术标签:

【中文标题】Swift 1D 字典到 2D【英文标题】:Swift 1D Dictionary to 2D 【发布时间】:2016-06-28 18:50:20 【问题描述】:

我在理解二维字典方面遇到了一点问题。我的函数必须返回带有部分的 UITableView 字典。 1 个模板类型可以有多个模板字符串。因此,当fetchedData 中有 2 个或更多具有相似类型的文本时,它们必须位于数组 [String] 中,并带有 1 个键 - 字符串。 从编译器的角度来看,下面的代码是绝对正确的。至于我,smth 是错误的,但是好的自动完成让我觉得一切都好。 显然它返回一个空字典[:]

func fetchTemplates() -> Dictionary<String, [String]> 
    var templates: Dictionary<String, [String]> = [:]
    let fetchRequest: NSFetchRequest<Template> = Template.fetchRequest()
    fetchRequest.sortDescriptors = [SortDescriptor.init(key: "templateType", ascending: true)]
    let fetchedData = try! context.fetch(fetchRequest)
    if (!fetchedData.isEmpty) 
        for templateItem in fetchedData 
            templates[templateItem.templateType!]?.append(templateItem.templateText!)
        
        return templates
    
    else 
        return templates
    

附: fetchedData 返回:

<Template: 0x003281h4> (entity: Template; id: 0x003281h4 <x-coredata:///Template/> ; data: 
    templateText = "Example";
    templateType = "First";
)

【问题讨论】:

旁注:没有必要检查!fetchedData.isEmpty。如果为空,则 for 循环将迭代 0 次,这意味着它会被跳过。 【参考方案1】:

问题出在这一行:

templates[templateItem.templateType!]?.append(templateItem.templateText!)

templates 使用以下行初始化:var templates: Dictionary&lt;String, [String]&gt; = [:]。此时,templates 是一个空字典。

让我们按时间顺序将这条线分解为发生的步骤:

    templateItem.templateType 被访问,并强制解包。如果是nil,则会发生崩溃。 templateItem.templateType! 用作templates 字典的键。这将始终返回nil。字典是空的,因此它没有任何键的值,包括这个。 ?.append() 被调用,条件是它没有被nil 调用。如果在nil 上调用它,则不会发生任何事情。

3 是您的问题的原因。如果键尚不存在,则需要初始化一个新数组:

func fetchTemplates() -> Dictionary<String, [String]> 
    var templates: Dictionary<String, [String]> = [:]
    let fetchRequest: NSFetchRequest<Template> = Template.fetchRequest()
    fetchRequest.sortDescriptors = [SortDescriptor.init(key: "templateType", ascending: true)]
    let fetchedData = try! context.fetch(fetchRequest)
    if (!fetchedData.isEmpty)  //see note 2
        for templateItem in fetchedData 
           let type = templateItem.templateType!
           var array = templates[type] ?? [] //see note 1
           array!.append(templateItem.templateText!)
           templates[type] = array
        
        return templates
    
    else 
        return templates
    

这个函数可以简化:

func fetchTemplates() -> [String : [String]] 
    let fetchRequest = Template.fetchRequest()
    fetchRequest.sortDescriptors = [SortDescriptor(key: "templateType", ascending: true)]

    let fetchedData = try! context.fetch(fetchRequest)

    var templates = [String, [String]]()
    for templateItem in fetchedData 
        let type = templateItem.templateType!
        templates[type] = (templates[text] ?? []) + [templateItem.templateText!]
    
    return templates

可以使用reduce代替:

func fetchTemplates() -> [String : [String]]  //see note 3
    let fetchRequest = Template.fetchRequest() //see note 4
    fetchRequest.sortDescriptors = [SortDescriptor(key: "templateType", ascending: true)] //see note 5

    let fetchedData = try! context.fetch(fetchRequest)

    return fetchedData.reduce([String, [String]]())templates, templateItem in
        (templates[templateItem.tempalteText!] ?? []) + [templateItem.templateText!]
     //see note 6

注意事项

    如果template[text] 不是nil,则分配给array。否则,将一个新数组 ([]) 分配给 `array。 这个检查是不必要的 Dictionary&lt;String, [String]&gt; 可以写成 [String : [String]] 无需显式类型签名 X.init() 可以写成 X() 空性检查是不必要的,整个for循环可以改成reduce调用。

【讨论】:

【参考方案2】:

问题是:

templates[templateItem.templateType!] 始终为nil,因为字典为空。

因此不能追加任何内容。

【讨论】:

以上是关于Swift 1D 字典到 2D的主要内容,如果未能解决你的问题,请参考以下文章

字典排序

Python 中的多维字典

在 Swift 中执行 println 字典项时转义字典键双引号

Python实用技法第6篇:让字典保持有序

将python字典翻译成C++

Python中实现按顺序遍历字典