Can you append to an array inside a dict? - swift

In Swift, you can declare a dict where the value is an array type, eg:
var dict: [Int: [Int]] = [:]
However, if you assign an array for a given key:
dict[1] = []
then it appears that Swift treats the array as immutable. For example, if we try:
(dict[1] as [Int]).append(0) // explicit cast to avoid DictionaryIndex
then we get the error 'immutable value of type [Int] has only mutating members named 'append''.
If we explicitly make the array mutable, then the append works, but doesn't modify the original array:
var arr = dict[1]!
arr.append(0) // OK, but dict[1] is unmodified
How can you append to an array which is a dict value?
More generally, how can you treat the values of a dictionary as mutable?
One workaround is to reassign the value afterwards, but this does not seem like good practice at all:
var arr = dict[1]!
arr.append(0)
dict[1] = arr

Try unwrapping the array instead of casting:
dict[1]!.append(0)

Related

Find the sum of an array in swift

I have an array that holds integer values. And I have defined it like so:
#State private var numbers: Array = []
the array is updated as the user uses the app. At a certain point, I need to find the sum of all the values in the array. Here is what I tried to do:
let sumOfNum = numberz.reduce(0, +)
However, this is giving me the following error on the plus(+) symbol:
Cannot convert value of type '(Int) -> Int' to expected argument type '(Int, Any) throws -> Int'
Not sure what the problem is. Any help or guidance would be appreciated.
Your issue is probably your Array declaration. You should declare is as an array of Int instead of an array of Any.
So your array declaration should be
#State private var numbers: [Int] = []

How to initialize OrderedDictionary - Swift Collections

Reading from the github docs I can see how to use it, but when I try to initialize it (to empty):
var responses: OrderedDictionary = [:]
it says: Empty collection literal requires an explicit type
I tried this:
var responses: OrderedDictionary<String: <TransactionsDataItemsClassAModel>> = [:]
but doesn't work, what's the proper way to initialize this?
This is how I have initialized my non ordered diccionary:
var dataDiccionary: [String: [TransactionsDataItemsClassAModel]] = [:]
Thanks
The regular syntax for generic types is like Array<T> and Dictionary<K, V>
There's short-hand syntax specific to Array and Dictionary: [T] and [K: V].
You're confusing some things and combined the two into an an invalid middle-ground.
OrderedDictionary doesn't have any special short-hands, so you would just treat it like any other generic type. The generic type parameters are specified with a comma separated list:
OrderedDictionary<String, [TransactionsDataItemsClassAModel]>

Using .sortInPlace within a .forEach closure Swift

I am attempting to sort the arrays within a dictionary, but am getting an error. Here is the code I have tried. What am I missing & why won't this compile?
var dict = [Int: [String]]()
dict[1] = ["Zack", "James", "Bill", "Quin", "Mike", "Adam"]
dict[1]?.sortInPlace()
dict.forEach{$0.1.sortInPlace()} // error: cannot use mutating member on immutable value of type '[String]'
Edit: I was able to get the following code to work after realizing that the for each loop assigns a constant by default:
db.forEach{db[$0.0] = $0.1.sort()}
Swift, by default assigns each value inside closure to be immutable. You can modify the default behavior by declaring the variable as mutable using var as this,
dict.forEach({ (key: Int, var value: [String]) in
value.sortInPlace()
print(value)
})

Mutating nested arrays in Swift Dictionary through custom accessor method

Say that we have a dictionary of arrays:
var dict: [Int: [Int]] = [:]
Is there something special about Dictionary's subscript methods? Can somebody explain why the following in-place append works:
dict[1] = []
dict[1]?.append(200)
// dict is now [1: [200]]
but the following doesn't:
var xs = dict[1]
xs?.append(300)
// dict is still [1: [200]], not [1: [200, 300]]
I (kind of) understand why the latter doesn't update the original dictionary, as it creates a copy of the array. But I don't understand why the first one works, I would assume that it similarly creates a copy.
More over (this is the actual problem I have), can I implement a method that allows similar in-place update behavior? The following code doesn't work:
extension Dictionary {
func mget(key: Key) -> Value? {
return self[key]
}
}
dict.mget(1)?.append(400)
It produces the following error:
49> d.mget(1)?.append(400)
repl.swift:49:12: error: immutable value of type '[Int]' only
has mutating members named 'append'
d.mget(1)?.append(400)
^ ~~~~~~

Difference between [] and []() in Swift

I tried searching around for what this is
[]()
But I'm not really sure. In a playground, I did this:
var test = [Int]();
test.append(1);
test.append(2);
If I leave off the () and do
var test = [Int];
test.append(1);
test.append(2);
It still looks like an array of Ints to me. What is the difference?
Type() means "call init()" - i.e., make a new instance of Type.
[Int] is a type, like String. [Int] means "array-of-Int".
String() makes a new empty String instance. [Int]() makes a new empty array-of-Int instance.
You can declare a variable as being of type array-of-Int. Or you can make and assign a new array-of-Int instance. Which is what you are doing here:
var test = [Int]()
But you cannot assign a type to a variable without further syntax. Thus, this is illegal:
var test = [Int]
EXTRA for experts
You can say:
var test = [Int].self
That does assign the type to the variable! That is unlikely to be what you want here, because now you have no array; you have a type, itself, as object!!
[Type] is syntactic sugar for Array<Type>, so it represents the array type, which is a generic struct, and for which you specify the type of elements it holds (Int in this example)
So the difference between:
[Int]
and
[Int]()
is the same as for
Array<Int>
and
Array<Int>()
The first is just a type, which you can use when declaring a variable or a function parameter.
The second invokes the parameterless constructor on that type, i.e. creates an instance of that type.