Add Multiple Key-Value pairs to an existing Dictionary [duplicate] - swift

This question already has answers here:
Dictionary extension to return a combined dictionary
(3 answers)
Closed 6 years ago.
I created a dictionary and it already has several values, however, I now want to add more. And I know that I can add key-value pairs like this:
var Dict = [Int: String] ()
Dict = [1: "one", 0: "zero"]
Dict[2] = "two"
Dict[3] = "tres"
But I was wondering how to add a lot of pairs at the same time, because if they are too many and it would be a really long process to do it like that.
I know this can be done in an Array like this:
Array += [1, 2, 3, 4, 5, 6]
But don't know if the same can be done for dictionaries.

There are some tricky things you can do with flatmap, but generally, Swift's Dictionary does not have the append(:Collection) method that Array does, because appending an unknown Dictionary could give you duplicate keys and cause errors. If you want to append another Dictionary, you'll have to iterate over it. This code
var dict1 : [String:String] = ["one" : "two", "three" : "four"]
var dict2 : [String:String] = ["one" : "two", "three" : "five"]
for(key, value) in dict2 {
dict1[key] = value
}
will replace all duplicate keys with the values in the second Dictionary. If you have no duplicate keys, this will do exactly what you want. If you DO have duplicate keys, then determine which values take priority, and make sure those values are in your dict2.

Related

Getting Key from Dict as String in Swift

New to coding here.
I have a dict with strings as keys and arrays of integers as values and I'm trying to get, from a given key, the String of that key. Not the value of the key, but the key itself. Now, I would just put an extra String into the array and call that, but my Xcode seems to have a bug where it really doesn't like having mixed type arrays and it doesn't work.
An example looks like this:
var allDict: [String: [Int]] = [:];
allDict.updateValue([1, 2, 3], forKey: "BAGEL"]);
allDict.updateValue([4, 5, 6], forKey: "DONUT"]);
allDict.updateValue([7, 8, 9], forKey: "MACARON"]);
I can get the values of each array quite fine with allDict["DONUT"]![1] //prints 5 for example, but what I want is to get the String of the key.
i.e. I would like to print DONUT using allDict["DONUT"]!
Is this possible? Thank you in advance!
It looks like you know your keys going in, in this example.
Here are a few ways you might recover your keys in a useful way, though:
Say you have a dictionary
var dict: [String: Int] = ...
You could get the array of keys:
let keys = dict.keys // keys is of type [String]
You can iterate over keys and values:
for (key, value) in dict {
...
}
You can merge dictionaries of and choose values from either dictionary when keys collide:
let mergedDict = dict.merge(otherDict) { leftValue, rightValue in
return leftValue
}
Addressing a version of your original question briefly:
Say you have the value for a certain key:
let donutValue = dict["DONUT"]
and somewhere else, where you lo longer have access to the key, you want to recover it from the value somehow. The best you could do is attempt to find the key by searching through the dictionary with the value you have.
var searchResult = dict.first { key, value in
return value == donutValue
}
This assumes the values in your dictionary are Equatable. Otherwise, you have to write some function or logic to figure out whether or not you've found that value in the dictionary corresponding to donutValue.

how to add multiple key value pairs to dictionary Swift

okay, i'm trying to have the user add a key and value pair to a dictionary i created and have it show up in a table view. i do that just fine but i cant seem to figure out how to add another pair. when i go to add another it replaces the last one. id really like to have multiple pairs. can someone help please?
heres my code:
//declaring the dictionary
var cart = [String:String]()
//attempting to add to dictionary
cart[pizzaNameLabel.text!] = formatter.stringFromNumber(total)
This is how dictionary works:
In computer science, an associative array, map, symbol table, or
dictionary is an abstract data type composed of a collection of (key,
value) pairs, such that each possible key appears at most once in the
collection.
So
var cart = [String:String]()
cart["key"] = "one"
cart["key"] = "two"
print(cart)
will print only "key" - "two" part. It seems that you may need an array of tuples instead:
var cart = [(String, String)]()
cart.append(("key", "one"))
cart.append(("key", "two"))
print(cart)
will print both pairs.
From Swift 5.0, you can use KeyValuePairs like ordered dictionary type with multiple keys.
See this Apple Document of KeyValuePairs. ;)
let recordTimes: KeyValuePairs = ["Florence Griffith-Joyner": 10.49,
"Evelyn Ashford": 10.76,
"Evelyn Ashford": 10.79,
"Marlies Gohr": 10.81]
print(recordTimes.first!)

Swift cannot append to subscript?

I can't seem to use .append() on a subscript.
For example, here's the array:
var arrayTest = [
"test": 8,
"test2": 4,
"anotherarry": [
"test4": 9
]
]
I am able to do this:
arrayTest.append(["test3": 3])
But I can't append to the array inside arrayTest. This is what I'm trying:
arrayTest["anotherarray"].append(["finaltest": 2])
First note: your variable arrayTest is a dictionary of type [String: NSObject], not an array. Similarly the value for the key anotherarray is also a dictionary.
Second note: you are setting the key anotherarry and retrieving the key anotherarray which would be nil in this example.
I'm also not sure how you are able to call append() on arrayTest since it is a dictionary and doesn't have that method.
But the key issue with what you are trying to do is that dictionaries and arrays are value types and are copied when passed around, rather than referenced. When you subscript arrayTest to get anotherarray, you are getting a copy of the value, not a reference to the value inside the dictionary.
If you want to modify something directly inside an array or dictionary (as opposed to replacing it), that something must be a reference type (a class). Here's an example of how your code could be accomplished:
var arrayTest = [
"test": 8,
"test2": 4,
"anotherarray": ([
"test4": 9
] as NSMutableDictionary)
]
(arrayTest["anotherarray"] as? NSMutableDictionary)?["test5"] = 10
Note that this code forces "anotherarray" to explicitly be an NSMutableDictionary (a class type from Objective-C) instead of defaulting to a Swift dictionary (a value type). That's what makes it possible to modify it from outside the dictionary, since it is now being passed as a reference and not copied.
Further Note:
As pointed out in the comments, using NSMutableDictionary is not something I personally recommend and isn't a pure Swift solution, it's just the way to arrive at a working example with the fewest changes to your code.
Your other options would include replacing the anotherarray value entirely with a modified copy instead of trying to subscript it directly, or if it's important for you to be able to chain your subscripts, you could create a class wrapper around a Swift dictionary like this:
class DictionaryReference<Key:Hashable, Value> : DictionaryLiteralConvertible, CustomStringConvertible {
private var dictionary = [Key : Value]()
var description: String {
return String(dictionary)
}
subscript (key:Key) -> Value? {
get {
return dictionary[key]
}
set {
dictionary[key] = newValue
}
}
required init(dictionaryLiteral elements: (Key, Value)...) {
for (key, value) in elements {
dictionary[key] = value
}
}
}
Then you would use it similarly to the NSMutableDictionary example:
var arrayTest = [
"test": 8,
"test2": 4,
"anotherarray": ([
"test4": 9
] as DictionaryReference<String, Int>)
]
(arrayTest["anotherarray"] as? DictionaryReference<String, Int>)?["test5"] = 10
For example, here's the array:
Nope, arrayTest is NOT an array. It's a dictionary.
I am able to do this...
No you're not. There is no such append method into a dictionary.
The problem
So it looks like you have a dictionary like this
var dict: [String:Any] = [
"test": 8,
"test2": 4,
"anotherdict": ["test4": 9]
]
You want to change the array inside the key anotherdict (yes I renamed your key) in order to add the following key/value pair
"finaltest": 2
Here's the code
if var anotherdict = dict["anotherdict"] as? [String:Int] {
anotherdict["finaltest"] = 2
dict["anotherdict"] = anotherdict
}
Result
[
"test2": 4,
"test": 8,
"anotherdict": ["test4": 9, "finaltest": 2]
]

how to make a swift dictionary that holds two items that are array of other items

I'd like to create a dictionary that holds two arrays (one key is called "locations" and the other is "items") like this:
var tmpResults = Dictionary("locations",Array)
tmpResults["items"]=Array
or something like this (neither of which seem to work):
var tmpResults = ["locations",:<Location>,"items":<Item>]
var tmpResults = ["locations":Array(Location),"items":Array(Item)]
but I'm really not sure how to do this in Swift. How would I specify the types that the arrays could hold?
I think the easiest solution would be AnyObject.
var tmpResults: [String: AnyObject] = [:]
tmpResults["locations"] = [location1, location2, location3]
tmpResults["items"] = [item1, item2, item3]
// Assuming location1, location2, and location3 are all of the same "Location" type
// And item1, item2, and item3 are all of the same "Item" type
By using AnyObject, your dictionaries objects could be almost anything. In this example, you have a dictionary that holds and array of Locations at one key, and an array of Items at another key.
You do lose some of the nice type-checking Swift does though.
Edit
In fact, you could declare it like this, so that the compiler at least knows your dictionary holds arrays:
var tmpResults: [String: [AnyObject]] = [:]
In either case, you use the array you'd probably do something like this:
if let items = tmpResults["items"] as? [Item] {
// Do something with you items here
}
In order to hold array in dictionary, you can go with the following code:
var tempResults : Dictionary<String, Array<String>>
This can be reduced to:
var tempResults : [String: [String]]
Then you can add your Array items to it:
var array1 : [String] = [String]()
array1.append("location1")
array1.append("location2")
array1.append("location3")
var array2 : [String] = [String]()
array2.append("item1")
array2.append("item2")
array2.append("item3")
And finally, you can add it to your Dictionary
tempResults["location"] = array1
tempResults["items"] = array2
Hope this helps!

How to add a extra values for the keys on dictionaries?

For the following variable
var dict2 = ["key1" : "value1", "key2" : [ "value1" , "value2" ]]
How to add a third value for the second key of the following dictionary?
If I can reformulate your dict2 declaration slightly:
var dict2 = ["key1" : ["value1"], "key2" : [ "value1" , "value2" ]]
then you can append an extra item to key2 like this:
dict2["key2"]?.append("value3")
However, you will probably need to be careful to check that key2 was already present. Otherwise, the above statement will do nothing. In which case you can write:
if dict2["key2"]?.append("value3") == nil {
dict2["key2"] = ["value3"]
}
Why did I change the original declaration? With the version I gave, dict2 will be of type [String:[String]]. But with your version, what Swift is doing is declaring a much more loosely typed [String:NSObject]. This compiles, but behaves very differently (contents will have reference not value semantics, you will have to do type checks and casts frequently etc), and is probably best avoided.
#AirspeedVelocity provides a working solution, but requiring a small change to the way the data is defined - but that is what I would do myself, if possible.
However if you have to stick with the original data format, you can use this code:
var dict2: [String : AnyObject] = ["key1" : "value1", "key2" : [ "value1" , "value2" ]]
var array = dict2["key2"] as? [String]
array?.append("value3")
dict2["key2"] = array
First we make explicit the dict2 type, a dictionary using strings as keys and AnyObject as values.
Next we extract the value for the key2 key, and attempt to cast to an array of strings - note that this returns an optional, so the type of array is [String]?
In the next line we add a new element to the array - note that if array is nil, the optional chaining expression evaluates to nil, and nothing happens
In the last line, we set the new array value back to the corresponding key - this step is required because the array is a value type, so when we extract it from the dictionary, we actually get a copy of it - so any update made on it won't be applied to the original array.