要设置转换的数组需要20秒 - Swift 3

时间:2017-03-17 11:47:12

标签: ios arrays swift core-data set

为什么从字符串数组转换为Set需要这么长时间?

我正在从Core Data读取数据并将获取的结果转换为字符串数组,然后从数组转换为集合。从阵列到设置的转换在模拟器中大约需要20秒。

如果Core Data中没有数据,我将文本文件读入字符串数组,然后将数组转换为集合。在这里进行转换只需不到1秒。

Core Data中的数据与文本文件相同,因为我将加载的文本文件保存到Core Data中。所以我转换的两个字符串数组应该是相同的吗?

有任何帮助吗?

将数组转换为~20秒

设置的函数
func coreData() {

    let appDelegate = UIApplication.shared.delegate as! AppDelegate // UIApplication.shared().delegate as! AppDelegate is now UIApplication.shared.delegate as! AppDelegate
    let context = appDelegate.persistentContainer.viewContext

    let request = NSFetchRequest<NSFetchRequestResult>(entityName: "Sowpods")
    request.returnsObjectsAsFaults = false

    do {
        let results = try context.fetch(request) as? [NSManagedObject] ?? []
        if results.count > 0 {
            print("Results fetched")

            // Load words from Core Data into wordSet
            let wordsArray = results.flatMap { $0.value(forKey: "words") as? String }

            let startTime = CFAbsoluteTimeGetCurrent()
            print("Putting fetched results from Array into Set")
            print("Words in array: \(wordsArray.count)")

            wordSet = Set(wordsArray.map { $0 }) /////// ~20 Seconds ///////////

            let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
            print("Time to put fetched results into wordSet: \(timeElapsed) s")

        } else {
            print("No results fetched from Core Data")
            // Read Dictionary

            wordSet = self.readDictionary(dictionaryFileName: "sowpods", dictionaryFileExtension: "txt")

            // Load words in dictionary into Core Data
            for word in wordSet {
                let newWord = NSEntityDescription.insertNewObject(forEntityName: "Sowpods", into: context)
                newWord.setValue(word, forKey: "words")
            }
            do {
                try context.save()
            } catch {
                print("Failed to save words")
            }
        }
    } catch {
        print("Couldn't fetch results")
    }
}

将数组转换为&lt;中设置的函数1秒

func readDictionary(dictionaryFileName: String, dictionaryFileExtension: String) -> Set<String> {
    print("Loading Dictionary")
    var wordsArray: [String] = []
    do {
        // This solution assumes  you've got the file in your bundle
        if let path = Bundle.main.path(forResource: dictionaryFileName, ofType: dictionaryFileExtension){
            let data = try String(contentsOfFile:path, encoding: String.Encoding.utf8)
            wordsArray = data.components(separatedBy: .newlines)
        }
    } catch let err as NSError {
        // do something with Error
        print(err)
    }

    let startTime = CFAbsoluteTimeGetCurrent()
    //print("Loading Dictionary")
    print("Words in array: \(wordsArray.count)")

    let dictionarySet = Set(wordsArray.map { $0 }) /////// < 1 Seconds ///////////

    let timeElapsed = CFAbsoluteTimeGetCurrent() - startTime
    print("Time to load dictionary Array into Set: \(timeElapsed) s")


    print("Done Loading Dictionary")
    return dictionarySet
}

从快速转换中记录

  • 未从Core Data获取结果
  • 正在加载词典
  • 数组中的单词:267627
  • 将字典数组加载到Set:0.7359259724617 s
  • 的时间
  • 完成加载词典

从慢速转化中记录

  • 取得的结果
  • 将从Array获取的结果放入Set
  • 数组中的单词:267627
  • 将获取的结果放入wordSet的时间:18.0488159656525 s

1 个答案:

答案 0 :(得分:1)

你从数据库中获得的字符串是否有尾随空格?

这可能会使它们比文本文件中的更长,导致Set的哈希算法更加努力并可能进入冲突。

在转换为Set时,我通过在238k字的词表中添加40个空格来测量3倍的时间。有了更多的空格和/或不同的单词,这可以解释部分(如果不是全部)你得到的20倍差异。

或者,或许,字典值与键#34;字&#34;每个记录包含多个单词(顾名思义),这也会使数组中的字符串更大,并且集合中的重复项可能更少。

您应该将文件的dictionarySet中的元素数量与数据库的wordSet进行比较。我怀疑由于某种原因,你可以在基于文件的集合中输入更少的条目(这也可以解释时差)。