创建键/值字典时,它将以随机排序的形式返回。我希望它们的顺序与它的创建顺序相同。
例如,请参阅此代码:
var dict = [
"kg": 1,
"g": 2,
"mg": 3,
"lb": 4,
"oz": 5,
"t": 6
]
println(dict)
返回以下内容:
[kg: 1, oz: 5, g: 2, mg: 3, lb: 4, t: 6]
如何保留声明字典的顺序?
答案 0 :(得分:14)
在您的情况下,自定义对象的数组可能更合适。 这是一个简单的示例,应该有助于您入门:
struct Unit : Printable {
let name: String
let factor: Double
// println() should print just the unit name:
var description: String { return name }
}
let units = [
Unit(name: "kg", factor: 1000.0),
Unit(name: "g", factor: 1.0),
Unit(name: "mg", factor: 0.001),
Unit(name: "lb", factor: 453.592292),
Unit(name: "oz", factor: 28.349523)
]
println(units) // [kg, g, mg, lb, oz]
(我不确定非公制单位因素是否正确:)
答案 1 :(得分:5)
正如Apple所说:
字典是键值关联的无序集合。
不知道这对你有帮助,但在这个链接中有一个ordereddictionary的实现: http://www.raywenderlich.com/82572/swift-generics-tutorial
答案 2 :(得分:3)
可悲的是,Apple只在Swift中内置了三个集合数据结构。这些是数组,字典和集合。幸运的是,Apple引入了一个非常广泛且功能强大的协议层次结构,支持轻松优雅地定义您自己的集合类。
因此,如果您不介意解决方案的额外空间(可能还有时间)复杂性,您可能希望选择构建自己的Swift集合类/结构,类似于保留元素顺序的Dictionary。通过将索引与键相关联,反之亦然,将其添加到其中。有关创建自己的集合数据结构的更多信息,请参阅文档:https://developer.apple.com/documentation/swift/collection。
我会给你一些帮助你的事情:
免责声明:此代码未经过测试,我在算法复杂性方面没有花费太多精力。请确定您的解决方案的要求,并自行检查以下代码是否符合。
public struct KeepOrderDictionary<Key, Value> where Key : Hashable
{
public private(set) var values: [Value]
fileprivate var keyToIndexMap: [Key:Int]
fileprivate var indexToKeyMap: [Int:Key]
public init()
{
self.values = [Value]()
self.keyToIndexMap = [Key:Int]()
self.indexToKeyMap = [Int:Key]()
}
public var count: Int
{ return values.count}
public mutating func add(key: Key, _ value: Value)
{
if let index = keyToIndexMap[key]
{ values[index] = value}
else
{
values.append(value)
keyToIndexMap[key] = values.count - 1
indexToKeyMap[values.count - 1] = key
}
}
public mutating func add(index: Int, _ value: Value) -> Bool
{
if let key = indexToKeyMap[index]
{
add(key: key, value)
return true
}
return false
}
public func get(key: Key) -> (Key, Value)?
{
if let index = keyToIndexMap[key]
{ return (key, values[index])}
return nil
}
public func get(index: Int) -> (Key, Value)?
{
if let key = indexToKeyMap[index]
{ return (key, values[index])}
return nil
}
public mutating func removeValue(forKey key: Key) -> Bool
{
guard let index = keyToIndexMap[key] else
{ return false}
values.remove(at: index)
keyToIndexMap.removeValue(forKey: key)
indexToKeyMap.removeValue(forKey: index)
return true
}
public mutating func removeValue(at index: Int) -> Bool
{
guard let key = indexToKeyMap[index] else
{ return false}
values.remove(at: index)
keyToIndexMap.removeValue(forKey: key)
indexToKeyMap.removeValue(forKey: index)
return true
}
}
extension KeepOrderDictionary
{
public subscript(key: Key) -> Value?
{
get
{ return get(key: key)?.1}
set
{
if let newValue = newValue
{ add(key: key, newValue)}
else
{ let _ = removeValue(forKey: key)}
}
}
public subscript(index: Int) -> Value?
{
get
{ return get(index: index)?.1}
set
{
if let newValue = newValue
{ let _ = add(index: index, newValue)}
}
}
}
extension KeepOrderDictionary : ExpressibleByDictionaryLiteral
{
public init(dictionaryLiteral elements: (Key, Value)...)
{
self.init()
for entry in elements
{ add(key: entry.0, entry.1)}
}
}
extension KeepOrderDictionary : Sequence
{
public typealias Iterator = IndexingIterator<[(key: Key, value: Value)]>
public func makeIterator() -> KeepOrderDictionary.Iterator
{
var content = [(key: Key, value: Value)]()
for i in 0 ..< count
{
if let value: Value = self[i], let key: Key = indexToKeyMap[i]
{ content.append((key: key, value: value))}
}
return content.makeIterator()
}
}
答案 3 :(得分:1)
let recordTimes: DictionaryLiteral = ["Florence Griffith-Joyner": 10.49,
"Evelyn Ashford": 10.76,
"Evelyn Ashford": 10.79,
"Marlies Gohr": 10.81]
print(recordTimes.first!)
// Prints "("Florence Griffith-Joyner", 10.49)"
不建议使用Xcode 10.2–10.2。更改为KeyValuePairs<Key, Value>
答案 4 :(得分:1)
我遇到了相同的问题,并通过https://github.com/noman200898/OrderedDictionary/blob/master/Sources/OrderedDictionary.swift类解决了 只需将此类添加到您的项目中,然后按如下所示使用它:
let testDic: OrderedDictionary = ["kg": 1, "g": 2, "mg": 3, "lb": 4, "oz": 5, "t": 6]
print(testDic)
print(testDic.unorderedDictionary)
print(testDic.orderedKeys)
print(testDic.orderedValues)
希望这会有所帮助。
答案 5 :(得分:0)
您可以做的一件事是对键值使用枚举而不是字符串文字。如果枚举具有Int rawValue,则可以编写一个基于原始值返回键的函数。然后,您可以使用for循环获取声明的顺序。例如
enum Months: Int{ case jan , feb, mar, apr }
let dict: Dictionary<Months, String> = [
.jan: "One",
.feb: "Two",
.mar: "Three",
.apr : "Four"
]
// This function returns key from enum rawValue. -- requires enum as key type with Int rawValue, but works for any value type.
func keyWithRawValue(_ rawValue: Int) -> Any? {
var key: Any?
for element in dict {
let rawAtElement = element.key.rawValue
if rawValue == rawAtElement {
key = element.key
}
}
return key
}
// use this for iterating through in declared order.
for index in 0...dict.count - 1 {
let key = keyWithRawValue(index) as! Months
print(dict[key]! )
}
输出:
One
Two
Three
Four
答案 6 :(得分:-1)
struct MenueItem {
let title : String
let image : String}
let items = [MenueItem(title: "Readers", image: "multimedia"),
MenueItem(title: "Live Broadcast", image: "multimedia"),
MenueItem(title: "Quran Browsing", image: "multimedia"),
MenueItem(title: "Personal Quran", image: "multimedia"),
MenueItem(title: "Videos", image: "multimedia"),
MenueItem(title: "Favorites", image: "favorites")]
...
override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return items.count
...
override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCellWithIdentifier("MenuTableViewCell", forIndexPath: indexPath) as! MenuTableViewCell
cell.cellTitle.text = items[indexPath.row].title
cell.cellImage.image = UIImage(named: items[indexPath.row].image)
return cell
}
}