Swift language: How do I implement a dictionary of array values, and assign (ie. append) new values to the array? - swift

Language: Swift
I declared a dictionary whose value is an array, like this:
var unloadedImagesRows = [String:[Int]]()
private func addToUnloadedImagesRow(row: Int, forLocation:String!) {
print("addToUnloadedImagesRow 0: row: \(row)")
var unloadedRows = imagesRowForLocation(forLocation)
unloadedRows!.append(row)
}
private func imagesRowForLocation(location:String!) -> [Int]! {
var unloadedRows = unloadedImagesRows[location];
if unloadedRows == nil {
unloadedRows = [Int]()
unloadedImagesRows[location] = unloadedRows
}
return unloadedRows
}
private func someMethod() {
addToUnloadedImagesRow(rowIndex, forLocation: event.iconImg)
...
}
The "unloadedRows!.append(row)" works and I saw in my debugger works as I saw the count increased to 1.
However, the next time I retrieve the value as in line "var unloadedRows = unloadedImagesRows[location]", I get a result of an array containing 0 values.
How do I implement a dictionary of array values, and assign (ie. append) new values to the array?

var unloadedRows = imagesRowForLocation(forLocation)
unloadedRows!.append(row)
unloadedImagesRows[forLocation] = unloadedRows!
You retrieve the array by value, i.e. another instance of the array stored inside the dictionary gets created. Therefore you should set it back into the dictionary after appending a value

Related

How to put a variable in a for loop with different end number

I’ve got multiple variables with the same name but a different number on the end like this:
MyVar1, MyVar2, MyVar3, MyVar4
and they are either true or false
How do I write this correctly?
For index in Range(1...4){
if (“MyVar” + index) == true{
print(“:)”)
}
}
didnt tries the solution but according to this post: https://stackoverflow.com/a/45622489/5464805 you can do this:
Edit: I read that your variables are Booleans
for i in 0...4 {
if let var = myObject.value(forKey: "MyVar\(i)") as Bool,
var { // If var is successfully cast and true it enters the statement
print(var)
}
}
HOWEVER
All the other solutions above or below are still correct. This is something you dont usually do in Swift in general unless you must do so.
You should either rewrite your model and give a proper name to each variables, that you will later put into an array such as...
class MyObject {
var MyVar1: Bool // To Rename
var MyVar2: Bool // To Rename
var MyVar3: Bool // To Rename
var MyVars: [Bool] {
get { return [MyVar1, MyVar2, MyVar3] }
}
}
Or you completely get rid of these variable and create an Array directly
class MyObject {
// var MyVar1: Bool // To Delete
// var MyVar2: Bool // To Delete
// var MyVar3: Bool // To Delete
var MyVars: [Bool]
}
and you set the Array / Dictionnary in accordance to your needs
You are trying to get a sum of String ("MyVar") and Int ("index") and compare that sum with Bool (true)
It would be more safety to store all your variables in an array like that
let myVars = [MyVar1, MyVar2, MyVar3, MyVar4]
Then you can iterate throught the array:
for i in myVars {
if i {
print(i)
}
}
You can't create a variable from concatenation at runtime , you need to have an array of bool like this
var arr = [false,true,true,false] // var1 , var2 , var3 , var4
for item in arr {
if item {
}
}

Mark closure element mutable Swift

I have 2 structs, first is:
struct LineData {
init (name: String,
colorValue: String,
values: [Int]){
self.name = name
self.colorValue = colorValue
self.values = values
}
private var cachedMaxValue: Int? = nil
let name: String
let colorValue: String
let values: [Int]
// describe max value for Y axis for specific Line
mutating func maxValue() -> Int{
if let cached = cachedMaxValue {
return cached
}
self.cachedMaxValue = values.max()
return cachedMaxValue ?? 0
}
}
Second have array of LineData structs:
struct CharData {
init(xAxis: XAxis,
lines: [LineData]){
self.xAxis = xAxis
self.lines = lines
}
private var cachedMaxValue: Int? = nil
var xAxis: XAxis
var lines: [LineData]
// describe max value for Y axis among lines
func maxValue() -> Int{
var maxValues: [Int] = []
lines.forEach{it in
maxValues.append(it.maxValue())
}
return 0
}
}
Code above not compile, because, of error on method maxValues for struct CharData. It says Cannot use mutating member on immutable value: 'it' is a 'let' constant
What i want is, iterate through an array of lines and among it max values find greater value.
Since lines is an ordinary array, how about simply:
for i in 0..<lines.count {
maxValues.append(lines[i].maxValue())
}
perhaps not quite as Swifty, but nothing gets copied. The optimizer ought to give you pretty much the same performance as forEach.
It's the it parameter/object in the forEach that's immutable. Just like the error says: "it is a let". You could probably do something like this:
lines.forEach { it in
var mutableIt = it
maxValues.append(mutableIt.maxValue())
}
It should be noted that this will create a mutable copy of the "it" struct instance.

Swift rating system loop and assign

Trying to build a rating system in Swift and looking for a cleaner way to loop through each of the values.
private func calculateRating(user: String) throws -> String {
let query = try Rating.makeQuery().filter("user", user).all()
var fiveStars = [Int]()
var fourStars = [Int]()
var threeStars = [Int]()
var twoStars = [Int]()
var onestar = [Int]()
if query.count > 1 {
for rating in query {
// Check each value and assign it to its associated value
// insert large if/else condition here :)
}
// Perform calculation and return value below
return ""
} else {
// Only one rating has been set
return query[0].value
}
}
Currently I'm looping through each of the values and assigning the rating to it's associated array fiveStars fourStars etc. I will then calculate the rating by the standard multiplication method. Is there a cleaner way to loop through the ratings and assign it to the relevant fiveStars array etc without creating a long if/else conditional?
Thanks
Edit: Sample output would be a single rounded up value out of 5 i.e. "4" out of five based on 1000's of multiple ratings.
let twoStars: [Int] = query.filter {$0.val == 2} .map {$0.val}
And so on.

How to remove duplicate data in the UIPickerView in Swift

May I know how to remove the duplicate data which all the data is passing from the Parse database. I just select one column and pass that column data to this picker view.
I've try to find the query.wherekey but it didn't have the DISTINCT function which similar to the SQL statement, so what should I do to avoid the data duplication?
As you add items one by one into your self.pickerString array, just verify if this array contains or not the new value before addObject new value to the array. For example:
if !self.pickerString.contains(object["Intake"] as! String) {
self.pickerString.append(object["Intake"] as! String)
}
There is no built-in function to remove duplicate items in an array in swift (correct me if I'm wrong). However, you can add new features for array with 'extension' keyword:
extension Array {
func distinct<T: Equatable>() -> [T] {
var newArray = [T]()
for item in self {
if !contains(newArray, item as! T) {
newArray.append(item as! T)
}
}
return newArray
}
}
usage:
let s = ["344","333","1","2","333"]
var p = s.distinct() as [String]
I don't think you have anything like distinct on Parse, you'll have to download all rows and then filter out equal values.
For a functional approach:
func distinct<T: Equatable>(source: [T]) -> [T] {
var unique = [T]()
for item in source {
if !contains(unique, item) {
unique.append(item)
}
}
return unique
}
[...]
self.pickerString = distinct(objects)
[...]

Assign string to Dictionary

I have this one:
var str:[String] = ["John:Computer Engineer","Melinda:Saler"]
and i want to assign to that
var myDictVal:[String:String]?
.....
Doing some operation. After done, the value of myDictVal will be:
myDictVal = ["John":"Computer" , "Melinda":"Saler"]
how I can assign string array to Dictionary variable?
Sorry for my english. Typing on my iphone.
The following will work, although you probably should add some sort of validation to make sure your strings have the proper format, especially if you're getting them from user input.
var stringArray:[String] = ["John:Computer Engineer", "Melinda:Saler"]
var myDictVal:[String:String] = Dictionary<String, String>()
for item in stringArray {
var myArray = item.componentsSeparatedByString(":")
var name:String = myArray[0]
var title:String = myArray[1]
myDictVal[name] = title
}
There are many ways of doing that - the solution I would choose is:
loop through all array elements, split each element by :, and create an array of (key, value) tuples
loop through all tuples, add to the dictionary
var res = str.map { (element: String) -> (key: String, value: String) in
var components = element.componentsSeparatedByString(":")
return (key: components[0], value: components[1])
}
for (key, value) in res {
myDictVal?[key] = value
}
Note that this version can throw a runtime exception if any of the array elements doesn't have the key:value format.