How to update dictionary value in Swift - swift

How to
get and
update
the specific element from the array in the dictionary?
var currency : [String: [Double]] = [
"EUR": [1,1],
"USD": [1.06,1.05],
"CHF": [1.07, 1.06]
]
I'm working on currency converter and I need to get eg. the second value (buy rate, in this case: "1.05") to make calculations.

let eur_exchangeRate = currency["EUR"]
This will give you the corresponding array of doubles from the dictionary.
let buyRate = eur_exchangeRate![1]
This will give you the second element in the array of doubles (which, I believe is the buy rate you're wanting to access)
currency["EUR"]![1] = 99
This will set your buy rate for EUROS to 99.
Please look at #vadian's comment on your question to get an idea of a cleaner implementation of these sort.

My tested solution in swift 4.2 for dictionary like [String : [String]]
yourDict![existingKey]![positionOfValueToUpdate] = newValue
example:
var myDict = [keyOne : ["valueA","valueB","valueC","valueD"]
let newValue = "valueX"
myDict![keyOne]![2] = newValue
after this myDict will be:
myDict = [keyOne : ["valueA","valueB","valueX","valueD"]

Related

Write to Nested Dictionary (Swift 4)

I have declared a dictionary in Swift as so: var dict = [String: [String: [String]]]().
What I am trying to do now is to write to the nested dictionary. I have used both codes below, however, none of them work as the initial key does not exist:
dict["Test"]?["One"] = ["Failed"]
dict["Test"]!["One"] = ["Failed"]
What I am trying to do is to create a key for ["One"], much like how you can create a key for a normal dictionary using dict[key].
You need to instantiate every inner dictionary.
var dict = [String : [String : [String]]]()
dict["Test"] = [String : [String]]()
dict["Test"]?["One"] = ["Worked"]
print(dict)
Make sure to avoid force unwrapping.
dict is empty. There is no value for the "Test" key.
One option is to provide a default:
dict["Test", default: [:]]["One"] = ["A", "B"]
You can take this one step further:
dict["Test2", default: [:]]["Two", default: []].append("Hello")
That last line will work for any combination of the keys "Test2" and "Two" existing or not before that is used.

Getting values out of dictionaries which have arrays as values

I have a dictionary which contains languages as values and the initial character of every language name (A, B, C, ...) as for the key.
var dictionary = [Character: [Language]]()
I would like to get all the languages out of the dictionary in the form of an array. To do so, I do
let languages = dictionary.values // Dictionary<Character, [Language]>.Values
That's not an array. I try to get the array like this
let languages = Array(tableViewSource.values) // [[Language]]
This returns an array of an array. How do I just get an array of languages? I saw the merge(_:uniquingKeysWith:) but I don't need to merge dictionaries.
You can try
let allLangs = nestedArr.reduce([], +)
Martin R's and Sh_Khan's answers outline the standard ways of doing this (you basically just want to flatten an array). However I'd like to show a more "manual" approach:
var langs = [String]()
for lang_list in dictionary.values {
langs.append(contentsOf: lang_list)
}
Alternatively, you can use the += operator instead of .append(contentsOf:). An easier way of doing this would be using flatMap(_:):
dictionary.values.flatMap { $0 }
If you want a single array (concatenating all dictionary values) then
Array(dictionary.values.joined())
does the trick. (This creates the final array without creating any additional intermediate arrays.)
Example:
let dictionary: [Character: [String]] = ["E": ["espanol", "english"], "G": ["german", "greek"]]
let langs = Array(dictionary.values.joined())
print(langs) // ["german", "greek", "espanol", "english"]
Note that the order of key/value pairs in a dictionary is unspecified.
An alternative is
let dictionary: [Character: [String]] = ["E": ["espanol", "english"], "G": ["german", "greek"]]
let langs = dictionary.keys.sorted().flatMap { dictionary[$0]! }
print(langs) // ["espanol", "english", "german", "greek"]
which gives the languages sorted by the corresponding keys.

<= Operand asking for expected type in Swift?

I'm trying to look for items equal or less than zero in my query like so.....
for zeroItems in snapshot.value as! NSDictionary where zeroItems.value["Value"] as! Int <= 0
I'm getting an Expected type error. Please explain and show me how to correct.
You may want to consider applying a filter to simplify the logic to only include elements less than zero. I've created a working example in the IBM Swift Sandbox.
import Foundation
// Construct the data structure with demo data
struct Snapshot {
let value: NSDictionary
}
let dict: NSDictionary = [ "a" : -1, "b" : 0, "c" : 1]
let snapshot = Snapshot(value: dict)
//Apply a filter
let zeroItems = snapshot.value.filter{Int($0.1 as! NSNumber) <= 0}
//View the result
print(zeroItems)
Almost certainly you've overused Any if you have to use this many as! casts in a single line. Create a custom struct for this type and convert the data to that. If you're passing around NSDictionary and using as! very much, you're fighting the system.
That said, to make this work you probably just need more parentheses. Something like:
for zeroItems in (snapshot.value as! NSDictionary) where (zeroItems.value["Value"] as! Int) <= 0
But this is horrible Swift, so avoid this if possible.
You interpreting snapshot.value as Dictionary, so zeroItems is a tuple of key and value.
As I understand you having array of dictionaries, and you want to filter them by "Value" key, right?
If so then you may use following code:
// dictionary with Value key, and Int value
let dict: [String: Any] = ["Value":-1]
// array of dictionaries
let value: [[String: Any]] = [dict, <**add here as many as you want**>]
// get only array of integeres
let onlyIntegers = value.flatMap { $0["Value"] as? Int }.filter {$0 <= 0 }
print(onlyIntegers)
// get array of dictionaries which passes <=0 check
let onlyLessOrEqualTo0 = value.filter { dict in
if let value = dict["Value"] as? Int {
return value <= 0
}
return false
}
print(onlyLessOrEqualTo0)
First of all, adding some parentheses will help in seeing where the problem is:
for zeroItems in myDict as! NSDictionary where (zeroItems.value["Value"] as! Int) <= 0
Now, we get "Type 'Any' has no subscript members". So the problem is that you haven't told Swift what the type is of zeroItems's value, which I think is a dictionary of , judging from your code:
This compiles for me:
for zeroItems in myDict as! Dictionary<String, Dictionary<String, Int>> where zeroItems.value["Value"]! <= 0
However, this is not pretty. You could probably get more readable code using filter as was suggested in another answer.

How can a sum multiple values from the same key across different dictionaries in swift?

I am new to Swift and iOS dev. in general. I was wondering how I could sum multiple values from the same key across different dictionaries. e.g. I have
20 dictionaries with the same key value pair [String: AnyObject] e.g. "Height": 20 I want to sum these and calculate the average.
EG:
// Example dictionary
let player17: [String: AnyObject] = [
"Name": "Les Clay",
"Height": 42,
"Soccer Experience": true,
"Guardian Name(s)": "Wynonna Brown"
]
//Used any object here as they all go into a big array
You can use reduce to add numbers up, like this:
let totalHeight = allPlayers.reduce(0) { (p, c) -> Int in
return p + (c["Height"] as! Int)
}
Note: The c["Height"] as! Int approach requires hard knowledge that "Height" key is present in every dictionary, and its value is of type Int. Otherwise, this will produce an exception at run time.
If some of your dictionaries do not have the proper key in them, or contain the value of a different type, you need to pre-filter or use an optional cast, for example
return p + ((c["Height"] as? Int) ?? 0)
Given
let players: [[String:AnyObject]] = ...
here's another approach
let sum = players.flatMap { $0["Height"] as? Int }.reduce(0, combine: +)
If a dictionary doesn't have a valid Int value for the "Height" key then that dictionary is ignored.

How do I add more items to this type of name value pair array? [duplicate]

I have a simple Dictionary which is defined like:
var dict : NSDictionary = [ 1 : "abc", 2 : "cde"]
Now I want to add an element into this dictionary: 3 : "efg"
How can I append 3 : "efg" into this existing dictionary?
You're using NSDictionary. Unless you explicitly need it to be that type for some reason, I recommend using a Swift dictionary.
You can pass a Swift dictionary to any function expecting NSDictionary without any extra work, because Dictionary<> and NSDictionary seamlessly bridge to each other. The advantage of the native Swift way is that the dictionary uses generic types, so if you define it with Int as the key and String as the value, you cannot mistakenly use keys and values of different types. (The compiler checks the types on your behalf.)
Based on what I see in your code, your dictionary uses Int as the key and String as the value. To create an instance and add an item at a later time you can use this code:
var dict = [1: "abc", 2: "cde"] // dict is of type Dictionary<Int, String>
dict[3] = "efg"
If you later need to assign it to a variable of NSDictionary type, just do an explicit cast:
let nsDict = dict as! NSDictionary
And, as mentioned earlier, if you want to pass it to a function expecting NSDictionary, pass it as-is without any cast or conversion.
you can add using the following way and change Dictionary to NSMutableDictionary
dict["key"] = "value"
I know this might be coming very late, but it may prove useful to someone.
So for appending key value pairs to dictionaries in swift, you can use updateValue(value: , forKey: ) method as follows :
var dict = [ 1 : "abc", 2 : "cde"]
dict.updateValue("efg", forKey: 3)
print(dict)
SWIFT 3 - XCODE 8.1
var dictionary = [Int:String]()
dictionary.updateValue(value: "Hola", forKey: 1)
dictionary.updateValue(value: "Hello", forKey: 2)
dictionary.updateValue(value: "Aloha", forKey: 3)
So, your dictionary contains:
dictionary[1: Hola, 2: Hello, 3: Aloha]
If your dictionary is Int to String you can do simply:
dict[3] = "efg"
If you mean adding elements to the value of the dictionary a possible solution:
var dict = Dictionary<String, Array<Int>>()
dict["key"]! += [1]
dict["key"]!.append(1)
dict["key"]?.append(1)
Swift 3+
Example to assign new values to Dictionary. You need to declare it as NSMutableDictionary:
var myDictionary: NSMutableDictionary = [:]
let newValue = 1
myDictionary["newKey"] = newValue
print(myDictionary)
For whoever reading this for swift 5.1+
// 1. Using updateValue to update the given key or add new if doesn't exist
var dictionary = [Int:String]()
dictionary.updateValue("egf", forKey: 3)
// 2. Using a dictionary[key]
var dictionary = [Int:String]()
dictionary[key] = "value"
// 3. Using subscript and mutating append for the value
var dictionary = [Int:[String]]()
dictionary[key, default: ["val"]].append("value")
In Swift, if you are using NSDictionary, you can use setValue:
dict.setValue("value", forKey: "key")
Given two dictionaries as below:
var dic1 = ["a": 1, "c": 2]
var dic2 = ["e": 3, "f": 4]
Here is how you can add all the items from dic2 to dic1:
dic2.forEach {
dic1[$0.key] = $0.value
}
Dict.updateValue updates value for existing key from dictionary or adds new new key-value pair if key does not exists.
Example-
var caseStatusParams: [String: AnyObject] = ["userId" : UserDefault.userID ]
caseStatusParams.updateValue("Hello" as AnyObject, forKey: "otherNotes")
Result-
▿ : 2 elements
- key : "userId"
- value : 866
▿ : 2 elements
- key : "otherNotes"
- value : "Hello"
[String:Any]
For the fellows using [String:Any] instead of Dictionary below is the extension
extension Dictionary where Key == String, Value == Any {
mutating func append(anotherDict:[String:Any]) {
for (key, value) in anotherDict {
self.updateValue(value, forKey: key)
}
}
}
As of Swift 5, the following code collection works.
// main dict to start with
var myDict : Dictionary = [ 1 : "abc", 2 : "cde"]
// dict(s) to be added to main dict
let myDictToMergeWith : Dictionary = [ 5 : "l m n"]
let myDictUpdated : Dictionary = [ 5 : "lmn"]
let myDictToBeMapped : Dictionary = [ 6 : "opq"]
myDict[3]="fgh"
myDict.updateValue("ijk", forKey: 4)
myDict.merge(myDictToMergeWith){(current, _) in current}
print(myDict)
myDict.merge(myDictUpdated){(_, new) in new}
print(myDict)
myDictToBeMapped.map {
myDict[$0.0] = $0.1
}
print(myDict)
To add new elements just set:
listParameters["your parameter"] = value
There is no function to append the data in dictionary. You just assign the value against new key in existing dictionary. it will automatically add value to the dictionary.
var param = ["Name":"Aloha","user" : "Aloha 2"]
param["questions"] = "Are you mine?"
print(param)
The output will be like
["Name":"Aloha","user" : "Aloha 2","questions" : ""Are you mine"?"]
To append a new key-value pair to a dictionary you simply have to set the value for the key. for eg.
// Initialize the Dictionary
var dict = ["name": "John", "surname": "Doe"]
// Add a new key with a value
dict["email"] = "john.doe#email.com"
print(dict)
Output -> ["surname": "Doe", "name": "John", "email": "john.doe#email.com"]
var dict = ["name": "Samira", "surname": "Sami"]
// Add a new enter code herekey with a value
dict["email"] = "sample#email.com"
print(dict)
Up till now the best way I have found to append data to a dictionary by using one of the higher order functions of Swift i.e. "reduce". Follow below code snippet:
newDictionary = oldDictionary.reduce(*newDictionary*) { r, e in var r = r; r[e.0] = e.1; return r }
#Dharmesh In your case, it will be,
newDictionary = dict.reduce([3 : "efg"]) { r, e in var r = r; r[e.0] = e.1; return r }
Please let me know if you find any issues in using above syntax.
Swift 5 happy coding
var tempDicData = NSMutableDictionary()
for temp in answerList {
tempDicData.setValue("your value", forKey: "your key")
}
I added Dictionary extension
extension Dictionary {
func cloneWith(_ dict: [Key: Value]) -> [Key: Value] {
var result = self
dict.forEach { key, value in result[key] = value }
return result
}
}
you can use cloneWith like this
newDictionary = dict.reduce([3 : "efg"]) { r, e in r.cloneWith(e) }
if you want to modify or update NSDictionary then
first of all typecast it as NSMutableDictionary
let newdictionary = NSDictionary as NSMutableDictionary
then simply use
newdictionary.setValue(value: AnyObject?, forKey: String)