【发布时间】:2017-03-17 11:47:11
【问题描述】:
为什么从字符串数组到 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")
}
}
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
- 将字典数组加载到集合中的时间:0.7359259724617 秒
- 完成加载字典
缓慢转换的日志
- 已获取结果
- 将从 Array 获取的结果放入 Set 中
- 数组中的单词:267627
- 将获取的结果放入 wordSet 的时间:18.0488159656525 秒
【问题讨论】:
-
Set(wordsArray) 怎么样?
-
使用returnsDistinctResults for the coreData
-
@Lu_ 不,同时使用
wordSet = Set(wordsArray) -
是的 - 你真的不想那样做。如果您想查看某个词是否存在,只需写一个
NSFetchRequest并计算一下。听起来像是另一个问题! -
你为什么在这里申请
.map{$0}?这对于将 Array 转换为 Set 不是必需的。但是,它迫使您制作数组的副本。此外,虽然可能很小,但您在一种情况下直接分配给属性,在另一种情况下直接分配给局部变量。如果wordSet包含didSet,那将是一个明显的区别。
标签: ios arrays swift core-data set