Array as a dictionary value in swift language - swift

I have the following swift dictionary
var List = [
2543 : [ "book", "pen" ],
2876 : [ "school", "house"]
]
How can i access the array values ?
println(List[2543][0])
The above code gives error "could not find member subscript"
and it should print "book"

Note that subscript returns an optional. We have to force unwrapping:
println(list[2543]![0])
Or use optional chaining
println(list[2543]?[0])

println(list[2543]![0])
Remember, dictionary subscript returns an Optional, not an array or whatever is inside the dictionary value.

Just try with following code:
var dic = List[0];
println("values \(dic)")
OR
println(list[2543]![0])

Related

How to add/Update key/values in dict in swift?

func exercise() {
var stockTickers: [String: String] = [
"APPL" : "Apple Inc",
"HOG": "Harley-Davidson Inc",
"BOOM": "Dynamic Materials",
"HEINY": "Heineken",
"BEN": "Franklin Resources Inc"
]
stockTickers["WORK"] = ["Slack Technologies Inc"]
stockTickers["BOOM"] = ["DMC Global Inc"]
print(stockTickers["WORK"]!)
print(stockTickers["BOOM"]!)
}
Error: Cannot assign value of type '[String]' to subscript of type 'String'
I do not understand the error, I'm new to swift, can someone guide me through this and tell mw why I see this error.
Alexander explained what you need to do in abstract terms. (Voted)
Specifically, change
stockTickers["WORK"] = ["Slack Technologies Inc"]
stockTickers["BOOM"] = ["DMC Global Inc"]
To
stockTickers["WORK"] = "Slack Technologies Inc"
stockTickers["BOOM"] = "DMC Global Inc"
The expression ["Slack Technologies Inc"] defines a String array containing a single string. That's not what you want. you defined a dictionary of type [String:String]
If you wanted your dictionary to have String keys and values that contained arrays of strings, you'd have to change the way you declared your dictionary:
var stockTickers: [String: [String]] = [
"APPL" : ["Apple Inc"],
"HOG": ["Harley-Davidson Inc"],
"BOOM": ["Dynamic Materials"],
"HEINY": ["Heineken"],
"BEN": ["Franklin Resources Inc"]
]
["DMC Global Inc"] is an array literal containing a string. It evaluates to a value of type [String] (a.k.a. Array<String>).
Thus the error makes sense: you’re trying to a assign an array of strings in a place where only a String is expected.
Just remove the square brackets.

Get value from multidimensional array in swift

I have the following array in Swift:
var words = [
"English" : ["Hello", "Bye"],
"Spanish" : ["Hola", "Adios"]
]
How can I get the value for index, something as the following doesn't work
print(words["English"][0])
It throws the error: Value of optional type Array? not unwrapped, did you mean to use ! or ? but that just makes it:
print(words["English"]?[0])
and still doesn't work, please help.
You need to look into how to unwrap optionals. For example, what you are trying to do could be done either of these two ways:
Force unwrapping:
print(words["English"]![0])
Safe unwrapping:
if let hello = words["English"]?[0]{
print(hello)
}

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]
]

Swift nested dictionary with nil

How can I have nil in the middle of nest Swift dictionaries?
var d: [String: AnyObject?] = [
"name": "Rodrigo",
"number": 1,
"nil": nil,
"more": [
"a": 1,
"b": 2,
"nil": nil
]
]
The second nil (inside "more") gives me the error Type of expression is ambiguous without more context.
The problem you're having here is that Swift's Dictionary is a value type, and therefore doesn't automatically conform to AnyObject. The compiler tries to help you out here, and bridge over to NSDictionary, which is an AnyObject, but unfortunately NSDictionary can't hold nil values, so you're out of luck.
As I see it, you have a couple options:
Go the standard Objective-C route and use NSNull() instead of nil in your nested array.
Rethink the structure of your data. Maybe instead of nested dictionaries, with string keys, you can build a struct PersonData that holds all the information you need in typed properties (including optionals). You may find that works even better than this approach.

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.