ios Swift - 字典中的存储值顺序完全改变
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/29601394/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Swift - Stored values order is completely changed in Dictionary
提问by McDonal_11
I tried to display datas which is in Dictionary format. Below, three attempts are there. First attempt, output order is completely changed. Second attempt, output order is same as input. But, in third attempt, I declared variable as NSDictionary. Exact output I received. Why this changes in Dictionary? Kindly guide me. I searched for Swift's Dictionary tag. But I couldn't found out.
我试图显示字典格式的数据。下面是三种尝试。第一次尝试,输出顺序完全改变。第二次尝试,输出顺序与输入相同。但是,在第三次尝试中,我将变量声明为 NSDictionary。我收到的确切输出。为什么这会在字典中发生变化?请指导我。我搜索了 Swift 的 Dictionary 标签。但是我查不出来。
//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;
}
ANOTHER QUERY: I have used play ground to verify. My screen shot is below:
另一个问题:我已经使用游乐场来验证。我的屏幕截图如下:
Here, In NSDictionary, I gave name5 as first, but in right side name2 is displaying, then, in println, it is displaying in ascending order. Why this is happening??
在这里,在 NSDictionary 中,我首先给出了 name5,但在右侧 name2 显示,然后,在 println 中,它以升序显示。为什么会这样??
Here, In Dictionary, I gave name5 as first, but in right side name2 is displaying, then, in println, it is displaying, how it is taken on the Dictionary line. Why this is happening??
在这里,在字典中,我首先给出了 name5,但在右侧显示了 name2,然后,在 println 中,它显示了它在 Dictionary 行上的显示方式。为什么会这样??
采纳答案by Schemetrical
This is because of the definition of Dictionaries:
这是因为 Dictionaries 的定义:
Dictionary
字典
A dictionary stores associations between keys of the same type and values of the same type in an collection with no defined ordering.
字典在集合中存储相同类型的键和相同类型的值之间的关联,没有定义的顺序。
There is noorder, they might come out differently than they were put in.
This is comparable to NSSet.
有没有订单,他们可能出来不同于并投入,
这与NSSet中。
Edit:
编辑:
NSDictionary
NSD字典
Dictionaries Collect Key-Value Pairs. Rather than simply maintaining an ordered or unordered collection of objects, an NSDictionary stores objects against given keys, which can then be used for retrieval.
字典收集键值对。NSDictionary 不是简单地维护一个有序或无序的对象集合,而是根据给定的键存储对象,然后可以将其用于检索。
There is alsonoorder, however there is sorting on print for debugging purposes.
目前还没有任何订单,但没有对打印排序进行调试。
回答by Leo Dabus
You can't sort a dictionary but you can sort its keys and loop through them as follow:
您不能对字典进行排序,但可以对其键进行排序并按如下方式循环遍历它们:
let myDictionary = ["name1" : "Loy", "name2" : "Roy", "name3" : "Tim", "name4" : "Steve"] // ["name1": "Loy", "name2": "Roy", "name3": "Tim", "name4": "Steve"]
let sorted = myDictionary.sorted {var user: KeyValuePairs<String, String> {
return ["FirstName": "NSDumb",
"Address": "some address value here",
"Age":"30"]
}
.key < .key} // or {["FirstName": "NSDumb", "Address": "some address value", "Age": "30"]
.value < .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)" )
}
回答by NSDumb
A little late for the party but if you want to maintain the order then use KeyValuePairs, the trade-off here is that if you use KeyValuePairs
you lose the capability of maintaining unique elements in your list
聚会有点晚了,但如果你想保持顺序,然后使用KeyValuePairs,这里的权衡是,如果你使用KeyValuePairs
你失去了在你的列表中维护唯一元素的能力
let array = [
("Apple", "Red"),
("Banana", "Yellow"),
// ...
]
prints
印刷
let dictionary = [
"Apple": "Red",
"Banana": "Yellow"
// ...
]
回答by grego
Dictionaries, by nature, are not designed to be ordered, meaning that they're not supposed to be (although they can be!).
字典本质上不是按顺序设计的,这意味着它们不应该是(尽管它们可以!)。
From the Dictionaries (Swift Standard Library documentation):
A dictionary is a type of hash table, providing fast access to the entries it contains. Each entry in the table is identified using its key, which is a hashable type such as a string or number. You use that key to retrieve the corresponding value, which can be any object. In other languages, similar data types are known as hashes or associated arrays.
字典是一种哈希表,提供对其包含的条目的快速访问。表中的每个条目都使用其键标识,键是可散列的类型,例如字符串或数字。您可以使用该键来检索相应的值,该值可以是任何对象。在其他语言中,类似的数据类型被称为散列或关联数组。
This requires some basic knowledge of Data Structures, which I'll outline & oversimplify briefly.
这需要一些数据结构的基本知识,我将简要概述和过度简化。
Storing associated data without a dictionary
在没有字典的情况下存储关联数据
Consider for a minute if there was no Dictionary and you had to use an array of tuples instead, to store some information about different fruits and their colors, as another answer suggested:
考虑一下,如果没有 Dictionary 并且您必须使用一组元组来代替存储有关不同水果及其颜色的一些信息,正如另一个答案所建议的那样:
// 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
If you wanted to find the color of a fruit you'd have to loop through each element and check its value for the fruit, then return the color portion.
如果您想找到水果的颜色,您必须遍历每个元素并检查水果的值,然后返回颜色部分。
Dictionaries optimize their storage using hash functionsto store their data using a unique hashthat represents the key that is being stored. For swift this means turning our key—in this case a String
—into an Int
. Swift uses Int
-based hashes, which we know because we all read the Hashable
protocol documentationand we see that Hashable
defines a hashValue
property that returns an Int
.
字典使用散列函数优化其存储,以使用代表正在存储的键的唯一散列来存储其数据。对于 swift 来说,这意味着将我们的密钥(在本例中为 a)转换String
为Int
. Swift 使用Int
基于的哈希,我们知道这是因为我们都阅读了Hashable
协议文档,我们看到它Hashable
定义了一个hashValue
返回Int
.
Storing associated data with a dictionary
使用字典存储关联数据
The benefits of using a dictionary are that you get fast read access and fast write access to data; it makes "looking up" associated data easy and quick. Typically O(1) time complexity, although the apple docs don't specify, maybe because it depends on the key type's hash function implementation.
使用字典的好处是可以快速读取数据和快速写入数据;它使“查找”相关数据变得简单快捷。通常 O(1) 时间复杂度,虽然苹果文档没有指定,可能是因为它取决于密钥类型的哈希函数实现。
dictionary["Lime"] = "Green" // pretend hashValue: 2
dictionary["Dragonfruit"] = "Pink" // pretend hashValue: 1
The trade off is that the order is typically not guaranteed to be preserved. Not guaranteedmeans that you might get lucky and it might be the same order, but it's not intended to be, so don't rely on it.
权衡是通常不能保证保留订单。不保证意味着您可能会很幸运,并且可能是相同的顺序,但这不是故意的,所以不要依赖它。
As an arbitrary example, maybe the string "Banana"
gets hashed into the number 0
, and "Apple"
becomes 4
. Since we now have an Int
we could, under the hood, represent our dictionary as an array of size 5:
作为一个任意的例子,也许字符串"Banana"
被散列到 number 中0
,并"Apple"
变成4
。由于我们现在有一个,Int
我们可以在引擎盖下将我们的字典表示为大小为 5 的数组:
// 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
You'll notice, we've converted our keys into array indices, and there are a bunch of blank spaces where we have nothing. Since we are using an array, we can insert data lightning fast, and retrieve it just as quickly.
你会注意到,我们已经将我们的键转换成数组索引,并且有一堆我们什么都没有的空格。由于我们使用的是数组,因此我们可以闪电般快速地插入数据,并同样快速地检索它。
Those nil
spaces are reserved for more values that may come later, but this is also why when we try to get values out of a dictionary, they might be nil. So when we decide to add more values, something like:
这些nil
空间是为以后可能出现的更多值保留的,但这也是为什么当我们尝试从字典中获取值时,它们可能为零。因此,当我们决定添加更多值时,例如:
Our dictionary, under the hood, may look like this:
我们的字典,在引擎盖下,可能是这样的:
##代码##As you can see, the values are not stored at all in the order we entered them. In fact, the keys aren't even really there. This is because the hash function has change our keys into something else, a set of Int
values that give us valid array indices for our actual storage mechanism, an array, which is hidden from the world.
如您所见,这些值根本没有按照我们输入的顺序存储。事实上,钥匙甚至都不在那里。这是因为散列函数已经将我们的键更改为其他东西,一组Int
值为我们的实际存储机制提供了有效的数组索引,这是一个对世界隐藏的数组。
I'm sure that was more information than you wanted and probably riddled with many inaccuracies, but it gives you the gist of how a dictionary works in practice and hopefully sounds better than, "that's just how it works."
我敢肯定,这些信息比您想要的要多,而且可能充满了许多不准确之处,但它为您提供了字典在实践中如何工作的要点,并且希望听起来比“这就是它的工作原理”更好。
When searching for the actual performance of Swift dictionaries, Is Swift dictionary ... indexed for performance? ... StackOverflowhad some extra possible relevant details to offer.
在搜索 Swift 字典的实际性能时,是否 Swift 字典...索引性能?... StackOverflow 提供了一些额外的可能相关细节。
If you're still interested to know more details about this, you can try implementing your own dictionary as an academic exercise. I'd also suggest picking up a book on Data Structures and Algorithms, there are many to choose from, unfortunately I don't have any suggestions for you.
如果您仍然有兴趣了解有关此的更多详细信息,您可以尝试实现自己的字典作为学术练习。我还建议你拿起一本关于数据结构和算法的书,有很多可供选择,不幸的是我没有给你任何建议。
The deeper you get into this topic the more you'll understand why you'll want to use one particular data structure over another.
您对这个主题了解得越深,就越会理解为什么要使用一种特定的数据结构而不是另一种。
Hope that helps!
希望有帮助!
回答by Greg Parker
Neither NSDictionary
nor Swift::Dictionary
orders its storage. The difference is that some NSDictionary
objects sort their output when printing and Swift::Dictionary
does not.
既不NSDictionary
也不Swift::Dictionary
命令其存储。不同之处在于,某些NSDictionary
对象在打印时对其输出进行排序,而Swift::Dictionary
不会对其进行排序。
From the documentation of -[NSDictionary description]
:
从文档-[NSDictionary description]
:
If each key in the dictionary is an NSString object, the entries are listed in ascending order by key, otherwise the order in which the entries are listed is undefined. This property is intended to produce readable output for debugging purposes, not for serializing data.
如果字典中的每个键都是一个 NSString 对象,则条目按键升序列出,否则列出条目的顺序未定义。此属性旨在为调试目的生成可读输出,而不是用于序列化数据。
回答by Antoine
This is indeed an issue with dictionaries. However, there's a library available to make sure the order stays the way you initialised it.
这确实是字典的问题。但是,有一个库可用于确保订单保持您初始化它的方式。
OrderedDictionary is a lightweight implementation of an ordered dictionary data structure in Swift.
The OrderedDictionary structure is an immutable generic collection which combines the features of Dictionary and Array from the Swift standard library. Like Dictionary it stores key-value pairs and maps each key to a value. Like Array it stores those pairs sorted and accessible by a zero-based integer index.
OrderedDictionary 是 Swift 中有序字典数据结构的轻量级实现。
OrderedDictionary 结构是一个不可变的泛型集合,它结合了 Swift 标准库中的 Dictionary 和 Array 的特性。与 Dictionary 一样,它存储键值对并将每个键映射到一个值。像 Array 一样,它存储那些按从零开始的整数索引排序和访问的对。
Check it out here: https://github.com/lukaskubanek/OrderedDictionary
回答by Jakub Vano
From The Swift Programming Language:
来自Swift 编程语言:
A dictionary stores associations between keys of the same type and values of the same type in an collection with no defined ordering.
字典在集合中存储相同类型的键和相同类型的值之间的关联,没有定义的排序。
Basically, order of items as seen in output is arbitrary, dependant on internal implementation of data structure, and should not be relied on.
基本上,输出中的项目顺序是任意的,取决于数据结构的内部实现,不应依赖。