Get the value of a Swift variable from a constructed name - swift

I am stuck at a problem which i am trying to figure out in Swift 4.
Let say, i have the below variables
let var1 = "One"
let var2 = "Two"
let var3 = "Three"
var counter = 1
// Loop Start
let currentVariable = "var" + "\(counter)"
//Fetch the value of variable stored under currentVariable
counter += 1
//Loop end
I am trying to get the value based on variable name stored under currentVariable.

You can set up dictionary, replacing your variable names with keys.
let letters = "ABCDEFGHIJKLMNOPQRSTUVWXYZ"
var myDictionary:[String:String] = ["var1":"One", "var2":"Two", "varA":"A", "varB":"B"] // note, both sides can be different types than String
for x in 0...9 {
let myKey = "var" + String(x)
printValue(myKey)
}
for x in letters.characters {
let myKey = "var" + String(x)
printValue(myKey)
}
The simple function:
func printValue(_ key:String) {
let myValue = myDictionary[key]
if myValue != nil {
print(myValue)
}
}
I'm pretty sure you can make things a bit more elegant, but you get the idea. Also, keep in mind that a Dictionary is "unordered", as opposed to an array.

Use an array
let myArray = ["one", "two", "three"];
var counter = 1;
print(myArray[counter]);

Related

Updating variable value from dictionary and best practice

As I progress into my Swift education, the time as come for me to ask for help about best practice and code optimization.
My app has become more and more complex every day and the current situation is as follows: I started using dictionaries and arguments to use a single function that can process a lot of different variables depending on the situation, which seems to be better practice than using 5 different functions that will do the same thing only with different variables.
I now have two files as follows:
Main1.swift:
class Main1 {
static var value1 : Int = 1
func updateValue(_ value: String) {
let dict : [String : Int] = ["value1": Main1.value1]
let dict1 = dict[value]
guard var value = dict1 else { return }
value = value + 1 // <- trying to update `static var value1`'s value from 1 to 2 here
print(value)
}
}
Main2.swift:
class Main2 {
func updateValue(_ value: String) {
let dict : [String : Int] = ["value1": Main1.value1] // <- thinking `value1` would now be 2
let dict1 = dict[value]
guard var value = dict1 else { return }
value = value + 1 // <- trying to get 3 here
print(value)
}
}
These classes are simplified versions of my code but the logic is the same: I am trying to use variables loaded from dictionaries and update their values to be used in another file and function:
Main1().updateValue("value1") //2
Main2().updateValue("value1") //2 <--- I need 3 here!
-> What exactly am I trying to achieve here?
To update the reference (static var value1 : Int = 1) value while accessing it through the convenience of a dictionary (or different method but you get the point about convenience).
In fact I am trying to do Main1.value1 = Main1.value1 + 1 while accessing Main1.value1 through a dictionary, which is impossible because I am not accessing the reference here.
I know this can't work, I have 3 different copies of value here but I don't how to update the variable value without using another global variable... I need your help to find a better logic.
I am open to any suggestion or thinking. I am not asking for code solution (which would be great anyway) but I'd love to have my education re-centered a little bit, I am starting to lose myself learning all by myself and the frustration comes from that I don't know what to be looking for anymore.
EDIT BASED ON COMMENTS
As per the comments below, here's a potential solution:
class Main1 {
static var dict: [String: Int] = ["value1": 1]
func updateValue(_ key: String) {
guard var value = dict[key] else { return }
value = value + 1
print(value)
dict[key] = value
}
}
ORIGINAL ANSWER
In Swift, [String : Int], String and Int are value types, as opposed to their Objective-C counterparts NSDictionary, NSString and NSNumber, which are reference types.
This means that when you do guard var value = dict1 else { return }, value is now a copy of what the dictionary contained, not a reference to that piece of data inside the dictionary.
So when you do value = value + 1 you're setting the new variables value, but not the contents of the dictionary.
Following your logic, you need to put value back into the dictionary, like this:
func updateValue(_ value: String) {
var dict : [String : Int] = ["value1": Main1.value1] // <- Change this to a var
let dict1 = dict[value]
guard var intValue = dict1 else { return }
intValue = intValue + 1 // <- trying to update `static var value1`'s value from 1 to 2 here
print(intValue)
dict[value] = intValue // <- ADD THIS
}

Swift3 loop dictionary to add value

I m new to programming I just playing around in playground, I am trying to loop in a dictionary to do some calculation and add them into new dictionary however, I can only add one dictionary value back. I am not sure why. Can anymore tell me and point out the point?
var name:String?
var popDict: [String: Array<Double>]?
var FinalDict: [String: Array<Double>]?
var mean: Double?
var elementSideArr: Array<Double>?
var nameArray = ["Olivia": [1,2,2,2,1,2,1,0.0001,0,1,2], "Amber": [52,52,65,66,57,63,62,0.0001,0,0,0]]
var doubleArr = [Double]()
for (key, value) in nameArray{
let thisValue = value
let arrayS = thisValue.prefix(7)
let slice = arrayS[0...6]
let popSideArr = Array(slice)
let average: Double = (popSideArr as NSArray).value(forKeyPath: "#avg.self") as! Double
mean = average
let thatValue = value
let arraySS = thatValue.suffix(3)
let sslice = arraySS[8...10]
elementSideArr = Array(sslice)
elementSideArr?.insert(average, at: 0)
let dict = ["\(key)": elementSideArr!]
for (key,value) in dict{
popDict = dict
}
}
print(popDict!)
["Olivia": [1.5714285714285714, 0.0, 1.0, 2.0]] // It is the only output but it should be 2 items.
Problem is in your inner for loop you are initializing whole new dictionary to popDict also you don't need for loop if you are having single key and value pair with your dictionary.
Replace line of codes:
let dict = ["\(key)": elementSideArr!]
for (key,value) in dict{
popDict = dict
}
With:
popDict["\(key)"] = elementSideArr!
Note: No need to cast swift array to NSArray to calculate average you can simply use reduce to get total and then divide the total with array count.
let array = popSideArr as? [Int] ?? []
let res = Double(array.reduce(0, +)) / Double(popSideArr.count)

swift 3 loop error (taking variable and adding it by itself)

My code does not work right now. I am trying to take names and add it by itself in the loop but the complier is giving me a error message and the code is not being printed.
let names = [Double(2),3,8] as [Any]
let count = names.count
for i in 0..<count {
print((names[i]) + names[i])
}
Because Any doesn't have + operator.
This will give you the result you expected.
If you want to add 2 values and print the result, you need to cast Any to calculatable like Double
let names = [Double(2),3,8] as [Any]
let count = names.count
for i in 0..<count {
if let value = names[i] as? Double {
print(value + value)
}
}
The use of as [Any] makes no sense. You can't add two objects of type Any which is probably what your error is about.
Simply drop it and your code works.
let names = [Double(2),3,8]
let count = names.count
for i in 0..<count {
print(names[i] + names[i])
}
Output:
4.0
6.0
16.0
Better yet:
let names = [Double(2),3,8]
for num in names {
print(num + num)
}

accessing inner dictionaries (dictionary of dictionaries) with one entry, when not knowing what key or value for that entry are

This is how I declared my dictionary:
var dataDictionary: [NSIndexPath:[Int:Bool]]!
The inner dictionary will always have just one entry e.g. [1:true]. When I search dataDictionary I specify a NSIndexPath. The inner dictionary gets returned. Sth like this:
var innerDictionary = dataDictionary[indexPath] // is of type [Int:Bool]
I would like to access inner dictionarys key and value, but I don't want to specify an Integer or Bool, because it is unknown. I only want to get that Int and/or Bool value stored in inner dictionary. No search of inner dictionary is needed, because if will always contains just one entry. Maybe something like this:
var key = innerDictionary.key
var value = innerDictionary.value
How can this be accomplished?
If your dictionary has only one entry, and you don't know the key, with Swift 2 you can get the first element of the keys sequence safely with if let:
let innerDictionary = [42: true]
if let k = innerDictionary.keys.first {
print(k) // prints 42
} else {
// dict is empty
}
Same for the value:
if let v = innerDictionary.values.first {
print(v) // prints true
} else {
// key has no value
}
Try by this way:
func nestedDic(){
var innerDictionary:NSDictionary = ["Item 1": "data 0", "Item 2": "data 1"]
//NSLog("original object:\(innerDictionary)")
NSLog("all keys array:\(innerDictionary.allKeys)")
if(innerDictionary.isKindOfClass(NSDictionary)){
for key in innerDictionary.allKeys{
let value = innerDictionary.valueForKey(key as! NSString as String)
NSLog("key value = \(value as! String)")
}
}
}
You could create a simple struct for the inner dictionary if there is only one entry, then you are able to use your favorite property names.
struct InnerDictionary {
var key = 0
var value = false
}
let indexPath = NSIndexPath(index: 1)
var dataDictionary = [indexPath: InnerDictionary(key: 1, value: true)]
if let innerDictionary = dataDictionary[indexPath] {
var key = innerDictionary.key
var value = innerDictionary.value
}

Nested Swift Dictionaries

I want to initialize a dictionary with a dictionary nested inside like this:
var a = [Int:[Int:Float]]()
a[1][2] = 12
But I get an error:
(Int:[Int:Float]) does not have a member named 'subscript'
I've hacked at a variety of other approaches, all of them running into some kind of issue.
Any idea why this doesn't work?
You can create your own 2D dictionary like this:
struct Dict2D<X:Hashable,Y:Hashable,V> {
var values = [X:[Y:V]]()
subscript (x:X, y:Y)->V? {
get { return values[x]?[y] }
set {
if values[x] == nil {
values[x] = [Y:V]()
}
values[x]![y] = newValue
}
}
}
var a = Dict2D<Int,Int,Float>()
a[1,2] = 12
println(a[1,2]) // Optional(12.0)
println(a[0,2]) // nil
The point is you access the element via a[x,y] instead of a[x][y] or a[x]?[y].
It's giving you that error because your first subscript returns an optional so it may return a dictionary or nil. In the case that it returns nil the second subscript would be invalid. You can force it to unwrap the optional value by using an exlamation point.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]![2]
If you aren't positive that a[1] is non-nil you may want to safely unwrap with a question mark instead.
var a = [1 : [ 2: 3.14]]
a[1]
a[1]?[2]
You can also assign using this method. (As of Beta 5)
var a = [Int:[Int:Float]]()
a[1] = [Int: Float]()
a[1]?[2] = 12.0
a[1]?[2] //12.0
Another way to do it is with an extension to the standard dictionary:
extension Dictionary {
mutating func updateValueForKey(key: Key, updater: ((previousValue: Value?) -> Value)) {
let previousValue = self[key]
self[key] = updater(previousValue: previousValue)
}
}
Example:
var a = [Int:[Int:Float]]()
a.updateValueForKey(1) { nestedDict in
var nestedDict = nestedDict ?? [Int:Float]()
nestedDict[2] = 12
return nestedDict
}