swift: changing dictionary values in an array that holds multiple maps - ios

I am trying to do the following but seems to be not acceptable operation. Perhaps I am missing something fundamental in the language.
var foo:NSArray = []
var bar = ["name":"jake"]
foo = [bar]
foo[0]["name"] = "Fred"
The last line throws an error saying '#lvalue $T8' is not identical to 'AnyObject!' Is this sort of thing not allowed in swift? If so how do one go about achieving this.

You just have to declare foo the right way. As an Array of Dictionaries:
var foo:[[String:AnyObject]] = []
var bar = ["name":"jake"]
foo = [bar]
foo[0]["name"] = "Fred"
foo // [["name": "Fred"]]

When you dereference with foo[0] the return type is AnyObject. The type AnyObject does not have a subscript operator. Use
(foo[0] as! [String:String])["name"]
Or, if your array will only hold dictionaries, then define it with:
var foo : [[String:String]] = []
Here is an example:
$ swift
Welcome to Swift version 1.2. Type :help for assistance.
1> var foo : [[String:String]] = []
foo: [[String : String]] = 0 values
2> var bar : [String:String] = ["name":"jake"]
3.
bar: [String : String] = {
[0] = {
key = "name"
value = "jake"
}
}
3> foo = [bar]
4> foo[0]["name"]
$R0: String? = "jake"

Related

"For-in loop requires '[String]?' to conform to 'Sequence'; did you mean to unwrap optional?" but I don't think I am using optionals

Here is what I'm trying to do but simplified down:
var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []
var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false } //I make an arr from a dictionary's keys of type [String:[String]]
for (key, val) in newdic{
for arr in adictionary[key]{
if !(adictionary[arr].contains(key)){
newdic[key] = true
}
}
}
I get these errors, when I run the above simplified version of the code I am trying to run in an ios app:
main.swift:12:28: error: value of optional type '[String]?' must be unwrapped to a value of type '[String]'
for arr in adictionary[key]{
main.swift:12:28: note: coalesce using '??' to provide a default when the optional value contains 'nil'
for arr in adictionary[key]{
main.swift:12:28: note: force-unwrap using '!' to abort execution if the optional value contains 'nil'
for arr in adictionary[key]{
I don't understand, what is wrong with what I am doing? What do these errors mean? It seems like Swift thinks I have an optional somewhere? But I don't see how I do... Any help is much appreciated.
If I change this line: for arr in adictionary[key]{
To: for arr in adictionary[key]!{
It fixes the issues and new errors appear on the if !(a... line. I still don't understand why that fixed it.
Swift dictionary accesses always return optional values, because the lookup will return nil if the key doesn't exist. It is up to you to handle this resulting optional is a safe way. Adding ! is rarely the right way to fix it because your code will crash if nil is returned.
The first time you get an optional is here:
for arr in adictionary[key] {
Again, Swift doesn't know if key exists in adictionary so it returns an optional. A safe way to fix this is to use the dictionary lookup which returns a default value when the key doesn't exist. In this case, returning an empty array seems like a good choice since your for loop will then just do nothing:
for arr in adictionary[key, default:[]] {
Next, you get an optional here:
if !(adictionary[arr].contains(key)){
Again, you need to decide how to safely handle the fact that dictionary[arr] could return nil. The same trick works here: return an empty array if arr doesn't exist:
if !(adictionary[arr, default:[]].contains(key)){
Here is the final version of your code:
var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []
var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false } //I make an arr from a dictionary's keys of type [String:[String]]
print(newdic)
for key in newdic.keys {
for arr in adictionary[key, default:[]] {
if !(adictionary[arr, default:[]].contains(key)){
newdic[key] = true
}
}
}
Here is a similar approach without having your mentioned problem.
var adictionary = [String:[String]]()
adictionary["A"] = ["B", "C"]
adictionary["B"] = ["A", "C"]
adictionary["C"] = ["A"]
adictionary["D"] = []
var newdic = Array(adictionary.keys).reduce(into: [String: Bool]()) { $0[$1] = false }
let notEmptValues = adictionary.values.filter { $0.count > 0 }.reduce([], +)
let duplicates = Array(Set(notEmptValues.filter { i in notEmptValues.filter { $0 == i }.count > 1 })).sorted(by: { $0 < $1 })
if let result = adictionary.first(where: { $0.value.sorted(by: { $0 < $1 }) == duplicates })?.key {
newdic[result] = true
}
print(newdic)

How to apply removeAtIndex for arrays of dictionary type in Swift?

I have dictionary of key-value type such as:
var images = [String:UIImage]()
If it's a normal array of strings, I can have the value removed by the following:
images.removeAtIndex(indexPath.row)
But if its argument type is dictionary then I it gives me the following error:
Cannot convert value of type 'Int' to expected argument type
'DictionaryIndex'.
How can I remove remove from such an array at a given index? Can anyone please help me on that?
You just remove the item with its String key.
images.removeValueForKey("someString")
Edit:
Per the comments:
I don't fully understand what you mean. Im going to recreate your scenario. But I will use Strings instead of UIImage's since I'm doing this on the command line.
1> var images = [String:String]()
images: [String : String] = 0 key/value pairs
2> images["one"] = "someting 1 2 3"
3> images["two"] = "something else 4 5 6"
4> images
$R0: [String : String] = 2 key/value pairs {
[0] = {
key = "one"
value = "someting 1 2 3"
}
[1] = {
key = "two"
value = "something else 4 5 6"
}
}
Now, based on your example, I want to remove an item.
5> images.removeValueForKey("one")
$R1: String? = "someting 1 2 3"
6> images
$R2: [String : String] = 1 key/value pair {
[0] = {
key = "two"
value = "something else 4 5 6"
}
}
Edit2:
After reading you commend and you example code a second time, I think you are misunderstanding what you have.
You have a dictionary of keys which are strings. Paired in a one to one relationship to UIImages.
So, if you remove one an item based on the key, you remove its only attribute which is an image.
Now, since you said the word array in your original question, I think this is what you want.
1> var images = [String:[String]]()
For you, it would be `var images = String:[UIImage]
Now you have an array of images per key.
images: [String : [String]] = 0 key/value pairs
1> images["one"] = [String]
2> images["one"]!.append("first")
3> images
$R0: [String : [String]] = 1 key/value pair {
[0] = {
key = "one"
value = 1 value {
[0] = "first"
}
}
}
4> images["one"]!.append("second")
5> images
$R1: [String : [String]] = 1 key/value pair {
[0] = {
key = "one"
value = 2 values {
[0] = "first"
[1] = "second"
}
}
}
6> images["one"]!.removeAtIndex(0)
$R2: String = "first"
7> images
$R3: [String : [String]] = 1 key/value pair {
[0] = {
key = "one"
value = 1 value {
[0] = "second"
}
}
}
You are declaring a Dictionary, not an Array:
var images = [String:UIImage]()
The key is type String, and there's only one value (UIImage) stored for a particular key. If you need an array of images for each string key, you could try:
var images = [String: Array<UIImage>]()
Then to access:
imageList = images["someKeyString"] // returns an array of UIImages
for image in imagelist {
//do something
}
enter image description here
CandyJar is a variable which created. remove command is used to remove the values as Index number/position.
CandyJar = {
[0] = "Apple"
[1] = "Mango"
[2] = "Orange"
[3] = "Straberry"
[4] = "Lemon"
}
//remove command will removed the Lemon value as Index mention is 4.
CandyJar.remove(at:4)
Returns:
$R6: String = "Lemon"
CandyJar
Returns:
$R7: [String] = 4 values {
[0] = "Apple"
[1] = "Mango"
[2] = "Orange"
[3] = "Strawberry"

How to convert dictionary to array

I want to convert my dictionary to an array, by showing each [String : Int] of the dictionary as a string in the array.
For example:
    
var myDict: [String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
    
I'm aware of myDict.keys.array and myDict.values.array, but I want them to show up in an array together. Here's what I mean:
    
var myDictConvertedToArray = ["attack 1", "defend 5", "block 12"]
You can use a for loop to iterate through the dictionary key/value pairs to construct your array:
var myDict: [String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
var arr = [String]()
for (key, value) in myDict {
arr.append("\(key) \(value)")
}
Note: Dictionaries are unordered, so the order of your array might not be what you expect.
In Swift 2 and later, this also can be done with map:
let arr = myDict.map { "\($0) \($1)" }
This can also be written as:
let arr = myDict.map { "\($0.key) \($0.value)" }
which is clearer if not as short.
The general case for creating an array out of ONLY VALUES of a dictionary in Swift 3 is (I assume it also works in older versions of swift):
let arrayFromDic = Array(dic.values.map{ $0 })
Example:
let dic = ["1":"a", "2":"b","3":"c"]
let ps = Array(dic.values.map{ $0 })
print("\(ps)")
for p in ps {
print("\(p)")
}
If you like concise code and prefer a functional approach, you can use the map method executed on the keys collection:
let array = Array(myDict.keys.map { "\($0) \(myDict[$0]!)" })
or, as suggested by #vacawama:
let array = myDict.keys.array.map { "\($0) \(myDict[$0]!)" }
which is functionally equivalent
With Swift 5
var myDict:[String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
let arrayValues = myDict.values.map({$0})
let arrayKeys = myDict.keys.map({$0})
You will have to go through and construct a new array yourself from the keys and the values.
Have a look at 's swift array documentation:
You can add a new item to the end of an array by calling the array’s
append(_:) method:
Try this:
var myDict:[String : Int] = ["attack" : 1, "defend" : 5, "block" : 12]
var dictArray: [String] = []
for (k, v) in myDict {
dictArray.append("\(k) \(v)")
}
Have a look at What's the cleanest way of applying map() to a dictionary in Swift? if you're using Swift 2.0:

Swift: How to add dictionary arrays to an array?

Can I add dictionary arrays (is this the correct term for a dictionary key holding multiple values?) to an array?
var dictionary = [String: [String]]()
var array = [String]()
var data1:String = "55a"
var data2:String = "95a"
var data3:String = "66"
var data4:String = "25"
var data5:String = "88b"
var data6:String = "#"
dictionary["3"] = [data1, data2, data3, data4, data5, data6]
var data7:String = "#"
var data8:String = "#"
var data9:String = "#"
var data10:String = "#"
var data11:String = "#"
var data12:String = "#"
dictionary["2"] = [data7, data8, data9, data10, data11, data12]
var data13:String = "100"
var data14:String = "101"
var data15:String = "102"
var data16:String = "103"
var data17:String = "104"
var data18:String = "105"
dictionary["1"] = [data13, data14, data15, data16, data17, data18]
I tried this:
array.extend([dictionary["1"], dictionary["2"], dictionary["3"]])
but there was an error "Cannot invoke 'extend' with an argument list of type '([[(String)?])"..
How do I add dictionary["1"], ["2"] & ["3"] accordingly into the array?
Your array type declaration is not correct. Please try below one
var array: [[String:[String]] = []
In case you are not interested in the order you might try:
array.extend(flatMap(dictionary.values, {$0}))
If order is important you might build your optionalArrays first:
let optionalArrays = [dictionary["1"], dictionary["2"], dictionary["3"]]
array.extend(flatMap(optionalArrays, {$0 ?? []}))
i.e. your dictionary returns an optional array, this causes the error you reported.
Hope this helps
If you wanted an array of arrays of Strings, you need to change your array's type to be [[String]], as the other answers said.
But, when getting values out of your dictionary, you shouldn't force unwrap! It may work for this example, but in the future you'll likely get into trouble with:
'fatal error: unexpectedly found nil while unwrapping an Optional
value'
You should check to see if a value exists in the dictionary for that key, using optional binding for example:
if let value = dictionary["1"] {
array.append(value)
}
// ...
Or, you could get all the values from your dictionary into an array like so:
let array = Array(dictionary.values)
If you actually did want an array of Strings, you could use flatMap:
let array = flatMap(dictionary.values) { $0 }
Your array variable must be an Array of Array with String elements.
Also don't forget to unwrap the values of the dictionaries by adding !.
Try this:
var dictionary = [String: [String]]()
var array = [[String]]()
var data1:String = "55a"
var data2:String = "95a"
var data3:String = "66"
var data4:String = "25"
var data5:String = "88b"
var data6:String = "#"
dictionary["3"] = [data1, data2, data3, data4, data5, data6]
var data7:String = "#"
var data8:String = "#"
var data9:String = "#"
var data10:String = "#"
var data11:String = "#"
var data12:String = "#"
dictionary["2"] = [data7, data8, data9, data10, data11, data12]
var data13:String = "100"
var data14:String = "101"
var data15:String = "102"
var data16:String = "103"
var data17:String = "104"
var data18:String = "105"
dictionary["1"] = [data13, data14, data15, data16, data17, data18]
array.extend([dictionary["1"]!, dictionary["2"]!, dictionary["3"]!])
Dictionary values are returned as optionals (thus indicating if a value exists for a key) so use the '!' to unwrap the values of each dictionary array (i.e. [dictionary["1"]!)
And as suggested in other answers change your array type as it currently defined as arrays of string rather then an array of dictionaries.

How to append associative array elements in Swift

How do I create and append to an associative array in Swift? I would think it should be something like the following (note that some values are strings and others are numbers):
var myArray = []
var make = "chevy"
var year = 2008
var color = "red"
myArray.append("trackMake":make,"trackYear":year,"trackColor":color)
The goal is to be able to have an array full of results where I can make a call such as:
println(myArray[0]["trackMake"]) //and get chevy
println(myArray[0]["trackColor"]) //and get red
Simply like this:
myArray.append(["trackMake":make,"trackYear":year,"trackColor":color])
Add the brackets. This will make it a hash and append that to the array.
In such cases make (extensive) use of let:
let dict = ["trackMake":make,"trackYear":year,"trackColor":color]
myArray.append(dict)
The above assumes that your myArray has been declared as
var myArray = [[String:AnyObject]]()
so the compiler knows that it will take dictionary elements.
I accept above answer.It is good.Even you have given correct answer,I like to give simplest way.The following steps are useful,if you guys follow that.Also if someone new in swift and if they go through this,they can easily understand the steps.
STEP 1 : Declare and initialize the variables
var array = Array<AnyObject>()
var dict = Dictionary<String, AnyObject>()
var make = "chevy"
var year = 2008
var color = "red"
STEP 2 : Set the Dictionary(adding keys and Values)
dict["trackMake"] = make
dict["trackYear"] = year
dict["trackColor"] = color
println("the dict is-\(dict)")
STEP 3 : Append the Dictionary to Array
array.append(dict)
println("the array is-\(array)")
STEP 4 : Get Array values to variable(create the variable for getting value)
let getMakeValue = array[0]["trackMake"]
let getYearValue = array[0]["trackYear"]
let getColorValue = array[0]["trackColor"]
println("the getMakeValue is - \(getMakeValue)")
println("the getYearValue is - \(getYearValue)")
println("the getColorVlaue is - \(getColorValue)")
STEP 5: If you want to get values to string, do the following steps
var stringMakeValue:String = getMakeValue as String
var stringYearValue:String = ("\(getYearValue as Int)")
var stringColorValue:String = getColorValue as String
println("the stringMakeValue is - \(stringMakeValue)")
println("the stringYearValue is - \(stringYearValue)")
println("the stringColorValue is - \(stringColorValue)")
STEP 6 : Finally the total output values are
the dict is-[trackMake: chevy, trackColor: red, trackYear: 2008]
the array is-[{
trackColor = red;
trackMake = chevy;
trackYear = 2008;
}]
the getMakeValue is - Optional(chevy)
the getYearValue is - Optional(2008)
the getColorVlaue is - Optional(red)
the stringMakeValue is - chevy
the stringYearValue is - 2008
the stringColorValue is - red
Thank You
This sounds like you are wanting an array of objects that represent vehicles. You can either have an array of dictionaries or an array of vehicle objects.
Likely you will want to go with an object as Swift arrays and dictionaries must be typed. So your dictionary with string keys to values of differing types would end up having the type [String : Any] and you would be stuck casting back and forth. This would make your array of type [[String : Any ]].
Using an object you would just have an array of that type. Say your vehicle object's type is named Vehicle, that would make your array of type [Vehicle] and each array access would return an instance of that type.
If I want to try it with my own statement. Which also I want to extend my array with the data in my dictionary and print just the key from dictionary:
var myArray = ["Abdurrahman","Yomna"]
var myDic: [String: Any] = [
"ahmed": 23,
"amal": 33,
"fahdad": 88]
for index in 1...3 {
let dict: [String: Any] = [
"key": "new value"
]
// get existing items, or create new array if doesn't exist
var existingItems = myDic[myArray] as? [[String: Any]] ?? [[String: Any]]()
// append the item
existingItems.append(myArray)
// replace back into `data`
myDic[myArray] = existingItems
}

Resources