【发布时间】:2020-03-26 09:10:32
【问题描述】:
我有一个包含超过 300k 个对象的数组,我在 UITableView 中显示了这些对象。使用 filter 方法按前缀匹配过滤时,第一次搜索需要 60 多秒!之后,搜索速度要快得多,大约需要 1 秒,我仍然想进一步改进。
对象如下所示:
struct Book {
let id: Int
let title: String
let author: String
let summary: String
}
这就是我目前的过滤方式:
filteredBooks = books.filter { $0.title.lowercased().hasPrefix(prefix.lowercased()) }
数据来自我使用Codable 解码的 JSON 文件(这也比我想要的要长一点)。我试图在没有数据库或任何类型的框架实现或延迟加载元素的情况下实现这一目标。我希望能够以不错的性能显示UITableView 和实时filter 中的300k 个对象。
我在 Google 上搜索了一下,找到了 Binary Search 和 Trie 搜索算法,但不知道如何实现它们才能将它们与 Codable 和我的 struct 一起使用。此外,也许用另一种数据类型替换 struct 会有所帮助,但也不确定是哪一种。
【问题讨论】:
-
300k 个对象大约是您应该开始使用数据库而不是大型 json 文件的时间。
-
@Alexander-ReinstateMonica 我知道,你是对的!但我已经知道如何使用数据库。这是一个测试项目,通过可能使用某种搜索算法来学习如何优化这样的极端情况:)
-
Book的步长为 56 字节,因此 300K 对象大约需要 16.8 MB。没关系,但是如果您要制作大量大型子集的副本,那将是一个问题。使用 trie 会起作用,但您需要将对象作为引用类型(类的对象,而不是结构)。在您的情况下,您可以构建一个前缀树,用于快速前缀查询。然而,这将是一个糟糕的用户体验,因为它对拼写错误、常见的拼写错误等完全不灵活。你不能搜索电影的中间(例如你不能搜索The Fellowship of the Ring,没有开头部分) -
@Alexander-ReinstateMonica 感谢您的评论。我已经看过
Trie结构,但我无法使用我的数据结构进行正确的实现。关于用户体验,这个不用太担心,我现在想关注prefixmatch :) -
这不就是我们在这里已经讨论过的关于半稳定分区的讨论吗? stackoverflow.com/questions/26173565/… 试试
removeAll(where:)或编写自己的分区算法。