Swift - 在Dictionary中完全更改了存储的值顺序

时间:2015-04-13 08:54:51

标签: ios swift nsdictionary

我尝试显示字典格式的数据。下面,有三次尝试。首次尝试,输出顺序完全改变。第二次尝试,输出顺序与输入相同。但是,在第三次尝试中,我将变量声明为NSDictionary。我收到了确切的输出。为什么这会改变字典?请指导我。我搜索了Swift的字典标签。但我找不到。

//First Attempt
var dict : Dictionary = ["name1" : "Loy", "name2" : "Roy"]
        println(dict)

//output:
[name2: Roy, name1: Loy]

//Second Attempt
var dict : Dictionary = ["name2" : "Loy", "name1" : "Roy"]
        println(dict)

//output:
[name2: Loy, name1: Roy]
-----------------------------------------------------------

//Third Attempt With NSDictionary
var dict : NSDictionary = ["name1" : "Loy", "name2" : "Roy"]
            println(dict)

//output:
{
    name1 = Loy;
    name2 = Roy;
}

另一个问题:我用过游戏场进行验证。我的屏幕截图如下:

play_ground_screen_shot

这里,在NSDictionary中,我首先给了name5,但是在右边name2显示,然后,在println中,它以升序显示。为什么会发生这种情况?

play_ground_screen_shot_2

这里,在字典中,我给了name5作为第一个,但是在右边name2正在显示,然后,在println中,它正在显示,它是如何在Dictionary行上拍摄的。为什么会发生这种情况?

8 个答案:

答案 0 :(得分:13)

这是因为字典的定义:

词典

  

字典存储相同类型的键与集合中相同类型的值之间的关联,但没有定义的顺序。

没有顺序,它们的出现方式可能不同于它们。
这与NSSet相当。


编辑:

的NSDictionary

  

字典收集键值对。 NSDictionary不是简单地维护有序或无序的对象集合,而是根据给定的密钥存储对象,然后可以将其用于检索。

还有 没有顺序,但是出于调试目的,打印时会进行排序。

答案 1 :(得分:9)

您无法对字典进行排序,但您可以对其键进行排序并按如下方式循环显示:

let myDictionary = ["name1" : "Loy", "name2" : "Roy", "name3" : "Tim", "name4" : "Steve"]   // ["name1": "Loy", "name2": "Roy", "name3": "Tim", "name4": "Steve"]


let sorted = myDictionary.sorted {$0.key < $1.key}  // or {$0.value < $1.value} to sort using the dictionary values
print(sorted) // "[(key: "name1", value: "Loy"), (key: "name2", value: "Roy"), (key: "name3", value: "Tim"), (key: "name4", value: "Steve")]\n"
for element in sorted {
    print("Key = \(element.key) Value = \(element.value)" )
}

答案 2 :(得分:1)

NSDictionarySwift::Dictionary都没有命令其存储空间。不同之处在于,某些NSDictionary个对象在打印时会对其输出进行排序,而Swift::Dictionary则不会。

来自-[NSDictionary description]的文档:

  

如果字典中的每个键都是NSString对象,则条目为   按键按升序排列,否则按顺序排列   列出的条目未定义。此属性旨在生产   可读输出用于调试目的,而不是用于序列化数据。

答案 3 :(得分:1)

这确实是字典的问题。但是,有一个库可用于确保订单保持初始化的方式。

  

OrderedDictionary是Swift中有序字典数据结构的轻量级实现。

     

OrderedDictionary结构是一个不可变的泛型集合,它结合了Swift标准库中Dictionary和Array的特性。与Dictionary类似,它存储键值对并将每个键映射到一个值。与Array类似,它存储那些通过从零开始的整数索引排序和访问的对。

在这里查看: https://github.com/lukaskubanek/OrderedDictionary

答案 4 :(得分:1)

从本质上讲,字典并不是按顺序排列的,这意味着它们不应该(尽管可以!)。

来自Dictionaries (Swift Standard Library documentation)

字典是一种哈希表,可以快速访问其中包含的条目。表中的每个条目都使用其键来标识,该键是可哈希的类型,例如字符串或数字。您可以使用该键检索相应的值,该值可以是任何对象。在其他语言中,类似的数据类型称为哈希或关联的数组。

这需要一些有关数据结构的基本知识,我将在其中简要概述和简化。


不使用字典存储关联数据

如果没有字典,请考虑一分钟,而必须使用元组数组来存储有关不同水果及其颜色的一些信息,作为另一个答案:

let array = [
   ("Apple", "Red"),
   ("Banana", "Yellow"),
   // ...
]

如果要查找水果的颜色,则必须遍历每个元素并检查水果的值,然后返回颜色部分。

字典使用hash functions优化存储,以使用唯一的 hash 表示要存储的密钥来存储数据。为了快速起见,这意味着将我们的密钥(在本例中为String)转换为Int。 Swift使用基于Int的哈希,这是众所周知的,因为我们都读过Hashable protocol documentation,并且我们看到Hashable定义了一个返回hashValue的{​​{1}}属性。


使用字典存储关联数据

使用字典的好处是您可以快速读取和访问数据。它使“查找”关联的数据变得轻松快捷。通常,O(1)的时间复杂度(尽管Apple文档未指定)可能是因为它取决于键类型的哈希函数实现。

Int

需要权衡的是通常不能保证保留订单。 不保证意味着您可能会很幸运,并且可能是相同的顺序,但这并不是故意的,所以请不要依赖它。

作为一个任意示例,也许字符串let dictionary = [ "Apple": "Red", "Banana": "Yellow" // ... ] 被散列为数字"Banana",而0变成了"Apple"。由于我们现在有了4,因此我们可以在幕后将字典表示为大小为5的数组:

Int

您会注意到,我们已经将键转换为数组索引,并且有很多空白。由于我们使用的是数组,因此我们可以快速插入数据并快速检索数据。

这些// what things *might* look like under, the hood, not our actual code // comments represent the array index numbers let privateArrayImplementationOfDictionary = [ "Yellow", // 0 nil, // 1 nil, // 2 nil, // 3 "Red", // 4 ] // count = 5 空格是为以后可能出现的更多值保留的,但这也是为什么当我们尝试从字典中获取值时它们可能为零的原因。因此,当我们决定添加更多值时,例如:

nil

我们的字典可能是这样的:

dictionary["Lime"] = "Green"        // pretend hashValue: 2
dictionary["Dragonfruit"] = "Pink"  // pretend hashValue: 1

如您所见,这些值根本没有按照我们输入的顺序存储。实际上,这些键甚至都没有。这是因为哈希函数将我们的键更改为其他键,一组// what things *might* look like under, the hood, not our actual code // comments represent the array index numbers let privateArrayImplementationOfDictionary = [ "Yellow", // 0 ("Banana") "Pink", // 1 ("Dragonfruit") "Green", // 2 ("Lime") nil, // 3 (unused space) "Red", // 4 ("Apple") ] // count = 5 值为我们的实际存储机制(一个隐藏于世界的数组)提供了有效的数组索引。


我敢肯定,这是比您想要的更多的信息,并且可能充斥着许多不准确的地方,但是它为您提供了词典在实践中如何工作的要旨,并希望听起来比“词典就是这样工作”要好。 >

在搜索Swift词典的实际性能时,Is Swift dictionary ... indexed for performance? ... StackOverflow还提供了一些可能的相关详细信息。

如果您仍然想了解有关此内容的更多详细信息,可以尝试将自己的词典作为学术练习来实施。我还建议您拿起一本有关数据结构和算法的书,有很多可供选择,不幸的是我没有任何建议。

您对本主题的了解越深,您就会越了解为什么要使用一种特定的数据结构而不是另一种。

希望有帮助!

答案 5 :(得分:0)

来自The Swift Programming Language

  

字典存储相同类型的键与具有无定义排序的集合中相同类型的值之间的关联。

基本上,输出中看到的项目顺序是任意的,取决于数据结构的内部实现,不应该依赖。

答案 6 :(得分:0)

聚会晚了一点,但是如果您想维持订单然后使用KeyValuePairs,那么这里的权衡是,如果您使用KeyValuePairs,则会失去在您的商品中维护唯一元素的能力列表

var user: KeyValuePairs<String, String> {
    return ["FirstName": "NSDumb",
            "Address": "some address value here",
            "Age":"30"]
}

打印

["FirstName": "NSDumb", "Address": "some address value", "Age": "30"]

答案 7 :(得分:0)

✅有可能!

虽然 Dictionary 没有排序,但您可以使用原始 Swift Repo< 中的官方 OrderedDictionary 使其保留初始顺序/strong>

有序集合当前包含:

他们说很快就会合并到 Swift 的源代码中(参考 WWDC21