Swift 1D字典到2D

时间:2016-06-28 18:50:20

标签: ios core-data nsdictionary swift3

我在理解二维词典方面遇到了一些问题。我的函数必须返回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
    }
}

P.S。 fetchedData返回:

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

2 个答案:

答案 0 :(得分:0)

问题是:

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

因此无法追加任何内容。

答案 1 :(得分:0)

问题在于这一行:

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

templates已使用此行初始化:var templates: Dictionary<String, [String]> = [:]。此时,templates是一个空字典。

让我们按照时间顺序将这一行分解为发生的步骤:

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

    注释

    1. 如果template[text]不是nil,则会将其分配给array。否则,将新数组([])分配给`array。
    2. 此检查是不必要的
    3. Dictionary<String, [String]>可以写为[String : [String]]
    4. 无需明确的类型签名
    5. X.init()可以写为X()
    6. 空洞检查是不必要的,整个for循环可以更改为reduce来电。
相关问题