【问题标题】:Its better to use a array, set or a dictionary for large number of items?对大量项目使用数组、集合或字典更好吗?
【发布时间】:2018-06-26 15:01:49
【问题描述】:

我的应用加载两个 json 文件,一个包含 27 个项目(州),另一个包含 5.000 个项目(城市),所有项目都是唯一的,json 示例:

state:{
        "_id": "58c0a61052effb00a396d399",
        "sigla": "AM",
        "descricao": "Amazonas"
}

city:{
      "_id": "5949767555cb9533e09c2932",
      "state": "58c0a6104ace7c56035f7691",
      "nome": "Abadia dos Dourados",
      "ibge": 3100104,
 }

我需要执行以下操作:

  • 搜索一个州的所有城市;

  • 在状态中搜索 id;

  • 在城市中搜索 id;

  • 在城市中搜索名称;

在这种情况下使用数组、集合还是字典更好?

【问题讨论】:

  • 5000 个条目足够小,您可以拥有以 id/name 等为每个城市的关键字的字典,但这确实是数据库的用途
  • 是的,我宁愿将您的过滤器查询到数据库,而不是下载所有内容并在本地搜索
  • @J.Doe 即使每个城市都是一千字节(它们不是,它们似乎在 150 左右),其中 5000 个只有 5 MB

标签: json swift dictionary


【解决方案1】:

要了解以下信息,您需要了解大 O 符号。简而言之,这是您的算法在最坏的情况下完成任务所需的步数。例如,如果元素位于最后一个位置,则将元素搜索到数组中最多需要 n 步。因此,在数组中搜索一个元素可以被认为是 O(n)。有关 O 表示法的更多参考资料,请查看此答案末尾的参考资料。

好的,知道了,现在您应该选择执行较少步骤的数据结构来完成您想要的任务。这将使您的算法更快,并且在某些情况下,这种差异可能很大。

根据 Raywenderlich 参考资料,以下是您询问的数据结构及其性能的一些信息:

数组

当项目的顺序很重要时使用数组。示例:按名字或姓氏排序的联系人、按日期排序的待办事项列表或其他需要按特定顺序查找或显示数据的情况。

根据 Apple 文档的性能:

  1. 创建 Swift Array 和 NSArray 在 O(log n) 和 O(n) 之间的降级速度大致相同。
  2. 访问特定索引处的任何值最坏的情况是 O(log n),但通常应该是 O(1)。
  3. 在未知索引处搜索对象的最坏情况为 O (n (log n)),但通常为 O(n)。
  4. 插入或删除对象最坏的情况是 O(n (log n)),但通常是 O(1)。

基本上,这些性能预期意味着当您知道对象的索引时数组是好的,主要使用 O(1) 操作。

字典

当您需要存储的内容没有特定的顺序,但数据具有有意义的关联时,最好使用字典。字典使用一种称为哈希表的数据结构,它可以提高与数组相关的一些性能。

根据 Apple 文档,字典的预期性能如下:

  1. 保证获得单个值的性能下降最坏的情况是 O(log n),但通常是 O(1)。
  2. 插入和删除可能与 O(n (log n)) 一样糟糕,但通常更接近 O(1)。

设置

集合是一种存储无序、唯一值的数据结构。独特是关键词;您将无法添加副本。

Apple 没有像对字典和数组那样概述对集合性能的总体预期,因此在这种情况下,您将只关注实际性能。

根据 Raywenderlich 的测试,set 的性能如下:

  1. 集创建复杂度约为 O(n)。
  2. 将对象添加到 NSSet 的时间接近 O(1),而使用 Swift 的 Set 结构时,它的降级速度可能高于 O(n)。
  3. 删除元素的时间约为 O(1)。
  4. 搜索元素的时间约为 O(1)。

结论

因此,对于您的情况,我建议使用以 id 作为键的字典,因为您的大多数搜索都会使用它。这主要意味着程序在字典中查找任何城市的步骤 O(1)。如果它是一个数组,如果你有 5000 个城市,它可能需要 5000 步。

您也可以使用集合,因为它在内部使用哈希。但是,我想在集合中,当您搜索实例对象城市而不是其中的属性时,此优势将很有用。例如:

let citiesSet = Set()
// add some cities into citiesSet
let city = City()
citiesSet.contains(city) //this search will be O(1)

我不确定上述信息,但我猜它是如何发生的(如果我错了,有人可以纠正我)。

对于按名称搜索城市,它仍然需要在字典中执行 n 步,因为名称不是关键。但这仍然比对所有操作都采取 n 步好哈哈。

您可以使用另一个以名称为键的字典,但这种数据重复对我来说听起来像是一个额外的复杂因素,因为您需要保证两个字典中的数据都是更新的。所以我不会那样做。

下面的 Raywenderlich 参考资料有助于更好地了解这些结构及其性能。我建议你阅读它。


参考资料:

Big O notation - Wikipedia

Data Structures in Swift - Raywenderlich

【讨论】:

  • Set 在内部也使用哈希表(因此需要Set 的元素符合Hashable,所以Set 查找是O(1) 就像 Dictionary 查找一样。查看 Collection Data Structures Swift 以获取有关不同 Swift 数据结构及其性能的更多信息。
  • 补充,这里是Apple's 上的Collections 的文档,下标为O(1),Sets 没有接受
  • 谢谢!我会根据情况调整答案。
猜你喜欢
  • 1970-01-01
  • 2011-01-26
  • 2017-05-05
  • 1970-01-01
  • 2015-11-17
  • 1970-01-01
  • 2010-12-30
  • 2019-02-06
  • 2021-06-28
相关资源
最近更新 更多