I can't seem to find a solution for how to type out the syntax. I want to access and be able to modify individual integers within an array that's nested in a larger dictionary.
Here's an example:
var exampleDictionary = [ 1: [2,3] , 2: [4,5] , 3: [7,8] ]
print (exampleDictionary[2]!) // prints [4,5]
How can I access the first value of Key 2 (4 above)?
How can I change just the first value of Key 2?
I'm trying things like this and it's not working:
exampleDictionary[2[0]] = (exampleDictionary[2[0]] - 3) // want to change [4,5] to [1,5]
print (exampleDictionary[2[0]]) // should print "1"
exampleDictionary[2 : [0]] = (exampleDictionary[2 :[0]] - 3)
print (exampleDictionary[2 : [0]])
You should subscript the array not its index :
exampleDictionary[2]![0] = (exampleDictionary[2]?[0] ?? 0) - 3
Safer would be to use optional binding like so:
if var array = exampleDictionary[2] {
array[0] -= 3
exampleDictionary[2] = array
}
You have always to consider that Swift collection types are value types and you have to modify the object in place, something like
if let firstValueOfKey2 = exampleDictionary[2]?.first {
print(firstValueOfKey2)
exampleDictionary[2]!.first = firstValueOfKey2 - 3
print(exampleDictionary[2]!.first!)
}
First of all you have dictionary of type [Int: [Int]], which means every key have a value of array from Int.
1.If your exampleDictionary is of unrelated type, Specify the type of exampleDictionary to [Int: [Int]] so that you won't need to cast it in next step.
var exampleDictionary: [Int: [Int]] = [ 1: [2,3] , 2: [4,5] , 3: [7,8] ]
2.Access the key you want.
var key2: [Int] = exampleDictionary[2]!
var firstValueOfKey2: Int = key2.first!
3.Change the value for key2:
key2 = [1,5]
4.Because of Swift, Collections are value type which means that a pointer refers to new block in memory, this means that you cant change the value from root object directly from modifiers. then you should assign the last result to root object.
exampleDictionary[2] = key2
Related
I'm new to coding and this is my first post!
I have created a dictionary in Swift where each individual value is an array.
Ex
1: [0.0443, 0.220832, 0.526799, 0.72147, 0.646954,0.511456,1.00405]
What I need to do is to access the value and store into a different array for data manipulation.
I am having trouble doing this because swift is viewing the array as a single object.
ex. dict[1]!.count will print 1 not 7 (ie. the 7 values)
Is there a way to do this - meaning to get swift to store the value as an array of Doubles?
Thanks.
It would be nice if you shared some code with us. but to access a dictionary of arrays you can do something like this :
let array1 = ["a", "b" , "c"]
let array2 : [Float] = [1.2,2.8,3.4]
let dictionary : Dictionary<String, Any> = ["array1" : array1, "array2" :array2]
var arrayFromDictionary = dictionary["array1"] as! [String]
var array2FromDictionary = dictionary["array2"] as! [Float]
print(arrayFromDictionary[1])
print(array2FromDictionary[2])
the first print call will print out "b" since it is the second member of the array1.
the second print call will print out 3.4 since it is the third member of array2.
does this answer your question ?
So in a swift playground file, I am trying to execute the following closure:
var list = [5, 4, 3]
var Arraymultiplier = {(list:Array) -> Array in
for value in list {
value*2
return list
}
}
Arraymultiplier(list)
When I do this though, I get an error saying that the generic type Array must be referenced in <..> brackets, but when I put the brackets, I get another error.
What's the right way to declare the array type as an input and a return?
Array is a generic type, meaning that it expects to see the actual type of the members of the array to be specified within < > immediately following Array:
var arrayMultiplier = {(list: Array<Int>) -> Array<Int> in
// do whatever you want here
}
Or, in the case of arrays, there is a convenient syntax that uses the [ ] characters and omits the need for Array reference at all:
var arrayMultiplier = {(list: [Int]) -> [Int] in
// do whatever you want here
}
I'm not sure what the original code sample was trying to do, but it looks like you might have been trying to build a new array with each item multiplied by 2. If so, then you might do something like:
let inputList = [5, 4, 3]
let arrayMultiplier = { (list: [Int]) -> [Int] in
var results = [Int]() // instantiate a new blank array of `Int`
for value in list { // iterate through array passed to us
results.append(value * 2) // multiply each `value` by `2` and add it to the `results`
}
return results // return results
}
let outputList = arrayMultiplier(inputList)
Or, obviously, you could efficiently achieve similar behavior using the map function:
let outputList = inputList.map { $0 * 2 }
I want to get a range of objects from an array. Something like this:
var array = [1,3,9,6,3,4,7,4,9]
var newArray = array[1...3] //[3,9,6]
The above would access elements from index 1 to 3.
Also this:
newArray = array[1,5,3] // [3,4,6] would be cool
This would retrieve elements from index 1, 5 and 3 respectively.
That last example can be achieved using PermutationGenerator:
let array = [1,3,9,6,3,4,7,4,9]
let perms = PermutationGenerator(elements: array, indices: [1,5,3])
// perms is now a sequence of the values in array at indices 1, 5 and 3:
for x in perms {
// iterate over x = 3, 4 and 6
}
If you really need an array (just the sequence may be enough for your purposes) you can pass it into Array's init method that takes a sequence:
let newArray = Array(perms)
// newArray is now [3, 4, 6]
For your first example - with arrays, that will work as-is. But it looks from your comments like you're trying it with strings as well. Strings in Swift are not random-access (for reasons relating to unicode). So you can't use integers, they have an String-specific bidirectional index type:
let s = "Hello, I must be going"
if let i = find(s, "I") {
// prints "I must be going"
println(s[i..<s.endIndex])
}
This works :
var n = 4
var newArray = array[0..<n]
In any case in
Slicing Arrays in Swift you'll find a very nice sample of the Python slice using a extension to Arrays in Swift.
How can I easily add elements to an array inside a dictionary?
It's always complaining with could not find member 'append' or could not find an overload for '+='
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
// all of these fail
dict["key"] += 4
dict["key"].append(4) // xcode suggests dict["key"].?.append(4) which also fails
dict["key"]!.append(4)
dict["key"]?.append(4)
// however, I can do this:
var arr = dict["key"]!
arr.append(4) // this alone doesn't affect dict because it's a value type (and was copied)
dict["key"] = arr
if I just assign the array to a var, modify it and then reassign it to the dict, won't I be copying everything? that wouldn't be efficient nor elegant.
Swift beta 5 has added this functionality, and you've nailed the new method in a couple of your attempts. The unwrapping operators ! and ? now pass through the value to either operators or method calls. That is to say, you can add to that array in any of these ways:
dict["key"]! += [4]
dict["key"]!.append(4)
dict["key"]?.append(4)
As always, be careful about which operator you use -- force unwrapping a value that isn't in your dictionary will give you a runtime error:
dict["no-key"]! += [5] // CRASH!
Whereas using optional chaining will fail silently:
dict["no-key"]?.append(5) // Did it work? Swift won't tell you...
Ideally you'd be able to use the new null coalescing operator ?? to address this second case, but right now that's not working.
Answer from pre-Swift beta 5:
It's a quirk of Swift that it's not possible to do what you're trying to do. The issue is that the value of any Optional variable is in fact a constant -- even when forcibly unwrapping. If we just define an Optional array, here's what we can and can't do:
var arr: Array<Int>? = [1, 2, 3]
arr[0] = 5
// doesn't work: you can't subscript an optional variable
arr![0] = 5
// doesn't work: constant arrays don't allow changing contents
arr += 4
// doesn't work: you can't append to an optional variable
arr! += 4
arr!.append(4)
// these don't work: constant arrays can't have their length changed
The reason you're having trouble with the dictionary is that subscripting a dictionary returns an Optional value, since there's no guarantee that the dictionary will have that key. Therefore, an array in a dictionary has the same behavior as the Optional array, above:
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
dict["key"][0] = 5 // doesn't work
dict["key"]![0] = 5 // doesn't work
dict["key"] += 4 // uh uh
dict["key"]! += 4 // still no
dict["key"]!.append(4) // nope
If you need to change something in an array in the dictionary you'll need to get a copy of the array, change it, and reassign, like this:
if var arr = dict["key"] {
arr.append(4)
dict["key"] = arr
}
ETA: Same technique works in Swift beta 3, though constant arrays no longer allow changes to contents.
The accepted answer bypasses the following much simpler possibility, which also works for older Swift versions:
var dict = Dictionary<String, Array<Int>>()
dict["key"] = [1, 2, 3]
print(dict)
dict["key", default: [Int]()].append(4)
print(dict)
This will print:
["key": [1, 2, 3]]
["key": [1, 2, 3, 4]]
And this:
var dict = Dictionary<String, Array<Int>>()
dict["key", default: [Int]()].append(4)
print(dict)
will print:
["key": [4]]
As a simple workaround you can use a NSMutableArray:
import Foundation
var dict = Dictionary<String, NSMutableArray>()
dict["key"] = [1, 2, 3] as NSMutableArray
dict["key"]!.addObject(4)
I am using effectively such simple solution in my project:
https://github.com/gui-dos/Guigna/blob/5c02f7e70c8ee3b2265f6916c6cbbe5cd3963fb5/Guigna-Swift/Guigna/GuignaAppDelegate.swift#L1150-L1157
Here is what I was telling Nate Cook, in the comments for his quality answer. This is what I consider "easily [adding] elements to an array inside a dictionary":
dict["key"] = dict["key"]! + 4
dict["key"] = dict["key"] ? dict["key"]! + 4 : [4]
For now, we need to define the + operator ourselves.
#infix func +<T>(array: T[], element: T) -> T[] {
var copy = array
copy += element
return copy
}
I think this version removes too much safety; maybe define it with a compound operator?
#infix func +<T>(array: T[]?, element: T) -> T[] {
return array ? array! + element : [element]
}
dict["key"] = dict["key"] + 4
Finally, this is the cleanest I can get it, but I'm confused about how array values/references work in this example.
#assignment func +=<T>(inout array: T[]?, element: T) {
array = array + element
}
dict["key"] += 5
Use 'for in', for getting values from dictionary's inside array. Here's an example to help you
var a = ["x":["a","b","c"], "y":["d"]]
for b in a {
print(b)
}
Output:
("x", ["d"])
("y", ["a", "b", "c"])
I know that true mutability can not be achieved in swift. I have an array interspersed with different types of contents.
let myArray = String[]();
var array = ["First","Second","Third",1,0.4,myArray,"dsaa"]
I learned from the above post I have linked that we will be able to append items to an array. But each time I add a new item to the array I have declared above I get this error:
could not find an overload for '+=' that accepts the supplied
arguments
But when the array is homogeneous, I am able to add an item which is same as the already present items, without hassle. but still the item with a different type can not be added.
If you declare your second array explicitly as AnyObject[], you can do it:
let myArray = String[]()
var array:AnyObject[] = ["First", "Second", "Third", 1, 0.4, myArray, "dsaa"]
let n1 = array.count // 7
array += "next"
let n2 = array.count // 8