Ordered map in Swift

IosSwiftDictionarySwift2

Ios Problem Overview


Is there any built-in way to create an ordered map in Swift 2? Arrays [T] are sorted by the order that objects are appended to it, but dictionaries [K : V] aren't ordered.

For example

var myArray: [String] = []
myArray.append("val1")
myArray.append("val2")
myArray.append("val3")

//will always print "val1, val2, val3"
print(myArray)


var myDictionary: [String : String] = [:]
myDictionary["key1"] = "val1"
myDictionary["key2"] = "val2"
myDictionary["key3"] = "val3"

//Will print "[key1: val1, key3: val3, key2: val2]"
//instead of "[key1: val1, key2: val2, key3: val3]"
print(myDictionary)

Are there any built-in ways to create an ordered key : value map that is ordered in the same way that an array is, or will I have to create my own class?

I would like to avoid creating my own class if at all possible, because whatever is included by Swift would most likely be more efficient.

Ios Solutions


Solution 1 - Ios

Just use an array of tuples instead. Sort by whatever you like. All "built-in".

var array = [(name: String, value: String)]()
// add elements
array.sort() { $0.name < $1.name }
// or
array.sort() { $0.0 < $1.0 }

Solution 2 - Ios

You can order them by having keys with type Int.

var myDictionary: [Int: [String: String]]?

or

var myDictionary: [Int: (String, String)]?

I recommend the first one since it is a more common format (JSON for example).

Solution 3 - Ios

"If you need an ordered collection of key-value pairs and don’t need the fast key lookup that Dictionary provides, see the DictionaryLiteral type for an alternative." - https://developer.apple.com/reference/swift/dictionary

Solution 4 - Ios

You can use KeyValuePairs, from documentation:

> Use a KeyValuePairs instance when you need an ordered collection of key-value pairs and don’t require the fast key lookup that the Dictionary type provides.

let pairs: KeyValuePairs = ["john": 1,"ben": 2,"bob": 3,"hans": 4]
print(pairs.first!)

//prints (key: "john", value: 1)

Solution 5 - Ios

if your keys confirm to Comparable, you can create a sorted dictionary from your unsorted dictionary as follows

let sortedDictionary = unsortedDictionary.sorted() { $0.key > $1.key }

Solution 6 - Ios

As Matt says, dictionaries (and sets) are unordered collections in Swift (and in Objective-C). This is by design.

If you want you can create an array of your dictionary's keys and sort that into any order you want, and then use it to fetch items from your dictionary.

NSDictionary has a method allKeys that gives you all the keys of your dictionary in an array. I seem to remember something similar for Swift Dictionary objects, but I'm not sure. I'm still learning the nuances of Swift.

EDIT:

For Swift Dictionaries it's someDictionary.keys

Solution 7 - Ios

Swift does not include any built-in ordered dictionary capability, and as far as I know, Swift 2 doesn't either

Then you shall create your own. You can check out these tutorials for help:

Solution 8 - Ios

I know i am l8 to the party but did you look into NSMutableOrderedSet ?

https://developer.apple.com/reference/foundation/nsorderedset

> You can use ordered sets as an alternative to arrays when the order of > elements is important and performance in testing whether an object is > contained in the set is a consideration—testing for membership of an > array is slower than testing for membership of a set.

Solution 9 - Ios

You can use the official OrderedDictionary from the original Swift Repo

The ordered collections currently contain:

They said it is going to be merged in the Swift itself soon (in WWDC21)

Solution 10 - Ios

    var orderedDictionary = [(key:String, value:String)]()

Solution 11 - Ios

As others have said, there's no built in support for this type of structure. It's possible they will add an implementation to the standard library at some point, but given it's relatively rare for it to be the best solution in most applications, so I wouldn't hold your breath.

One alternative is the OrderedDictionary project. Since it adheres to BidirectionalCollection you get most of the same APIs you're probably used to using with other Collection Types, and it appears to be (currently) reasonably well maintained.

Solution 12 - Ios

Here's what I did, pretty straightforward:

let array = [    ["foo": "bar"],
    ["foo": "bar"],
    ["foo": "bar"],
    ["foo": "bar"],
    ["foo": "bar"],
    ["foo": "bar"]
]

// usage
for item in array {
    let key = item.keys.first!
    let value = item.values.first!
    
    print(key, value)
}

Keys aren't unique as this isn't a Dictionary but an Array but you can use the array keys.

Solution 13 - Ios

use Dictionary.enumerated()

example:

let dict = [    "foo": 1,    "bar": 2,    "baz": 3,    "hoge": 4,    "qux": 5]


for (offset: offset, element: (key: key, value: value)) in dict.enumerated() {
    print("\(offset): '\(key)':\(value)")
}
// Prints "0: 'bar':2"
// Prints "1: 'hoge':4"
// Prints "2: 'qux':5"
// Prints "3: 'baz':3"
// Prints "4: 'foo':1"

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJojodmoView Question on Stackoverflow
Solution 1 - IosMundiView Answer on Stackoverflow
Solution 2 - IoschrisamanseView Answer on Stackoverflow
Solution 3 - IoscoffeecoderView Answer on Stackoverflow
Solution 4 - Iosbarola_mesView Answer on Stackoverflow
Solution 5 - IosDeep ParekhView Answer on Stackoverflow
Solution 6 - IosDuncan CView Answer on Stackoverflow
Solution 7 - IosenesView Answer on Stackoverflow
Solution 8 - IosAkademiksQcView Answer on Stackoverflow
Solution 9 - IosMojtaba HosseiniView Answer on Stackoverflow
Solution 10 - IosJay ZiView Answer on Stackoverflow
Solution 11 - IosGetSwiftyView Answer on Stackoverflow
Solution 12 - IosSkouaView Answer on Stackoverflow
Solution 13 - IossweetswiftView Answer on Stackoverflow