最好为大量项目使用数组,集合或字典吗?

时间:2018-01-17 16:44:27

标签: json swift dictionary

我的应用程序加载了两个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;

  • 在城市中搜索名称;

最好在这种情况下使用数组,集合或字典吗?

1 个答案:

答案 0 :(得分:2)

要了解以下信息,您需要了解 Big O表示法。简而言之,这是您的算法将采取的步骤数,在最坏的情况下,完成它的任务。例如,如果元素进入最后位置,则将元素搜索到数组中将在最坏情况下执行 n 步骤。因此,搜索数组中的元素可以被认为是O(n)。有关O符号的更多参考,请查看本答案末尾的参考文献。

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

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

<强>阵列

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

根据Apple的文档表现:

  1. 创建一个Swift数组和一个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)。
  5. 基本上,这些性能预期意味着当您知道对象的索引时,数组很好,主要使用O(1)操作。

    <强>词典

    当您需要存储特定订单时,最好使用字典,但数据具有有意义的关联。字典使用称为哈希表的数据结构,它允许与数组相关的一些性能改进。

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

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

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

      Apple没有像设置字典和数组一样勾勒出对设定性能的整体期望,因此在这种情况下,您只关注现实世界的表现。

      根据Raywenderlich的测试,集合的表现是:

      1. 设置创建复杂度大约为O(n)。
      2. 将对象添加到NSSet会保持在O(1)附近,而使用Swift的Set结构可能会以高于O(n)的速率降级。
      3. 删除元素大约是O(1)。
      4. 搜索元素大约是O(1)。
      5. 结论

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

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

        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