Swift - Replace a value in a nested struct - swift

I need to mutate nested dictionaries of unknown depth.
I realize that structs in swift are value types when in fact i would need a reference type ("NSMutable")
But I've noticed that if I access nested structs using dot(.) syntax I am able to update a value directly, without the need to reassign to the original "parent".
For instance In a case of nested arrays:
var l1 = ["a0","b0"]
var l2 = ["a1","b1"]
var list = [l1,l2]
print(list)
>>[["a0", "b0"], ["a1", "b1"]]
// I can mutate the nested structs by using dot(.) syntax
// mutate the zero indexed nested array:
list[0].insert("x0", atIndex: 0)
print(list)
>> [["x0", "a0", "b0"], ["a1", "b1"]]
// try to mutate after assignment - Not able to
var l1Ref = list[0]
print(l1Ref)
>> ["x0", "a0", "b0"]
l1Ref.removeFirst()
print(l1Ref)
>> ["a0", "b0"]
print(list)
// still the same as was before
>> [["x0", "a0", "b0"], ["a1", "b1"]]
How can I mutate the nested struct iteratively without using dot syntax?

Arrays are structures in Swift and when you assignment a subarray to a variable you got a copy of the subarray.
To get a reference to the subarray define type of your array as array of NSMutableArrays:
var array: [NSMutableArray] = [["a", "b", "c"]]
var subArray = array[0]
subArray.removeObjectAtIndex(1)
print(array, subArray)
>> [(a, c)] [(a, c)]
You can read more about Arrays in Swift here

Related

Why result of reversed() does behave itself like being an Array? [duplicate]

I'm wondering about the reversed() method on a swift Array:
var items = ["a", "b", "c"]
items = items.reversed()
the signature of the reversed method from the Apple doc says that it returns a
ReversedRandomAccessCollection<Array<Element>>
could that be assigned back to items without doing what the apple doc say which is
For example, to get the reversed version of an array, initialize a new Array instance from the result of this reversed() method.
or would it give problem in the future? (since the compiler doesn't complain)
There are 3 overloads of reversed() for an Array in Swift 3:
Treating the Array as a RandomAccessCollection,func reversed() -> ReversedRandomAccessCollection<Self> (O(1))
Treating the Array as a BidirectionalCollection,func reversed() -> ReversedCollection<Self> (O(1))
Treating the Array as a Sequence,func reversed() -> [Self.Iterator.Element] (O(n))
By default, reversed() pick the RandomAccessCollection's overload and return a ReversedRandomAccessCollection. However, when you write
items = items.reversed()
you are forcing the RHS to return a type convertible to the LHS ([String]). Thus, only the 3rd overload that returns an array will be chosen.
That overload will copy the whole sequence (thus O(n)), so there is no problem overwriting the original array.
Instead of items = items.reversed(), which creates a copy of the array, reverse that and copy it back, you could reach the same effect using the mutating function items.reverse(), which does the reversion in-place without copying the array twice.

Swift array address is not same as &array[0]

Document said:
An in-out expression that contains a mutable variable, property, or subscript reference of type Type, which is passed as a pointer to the address of the left-hand side identifier.
A [Type] value, which is passed as a pointer to the start of the array.
But when I run the following code :
func print<Type>(unsafePointer pointer: UnsafePointer<Type>) {
print("\(pointer) ==> \(pointer.pointee) : \(Type.self)")
}
var array = [1, 2, 3, 4]
print(unsafePointer: array)
print(unsafePointer: &array[0])
I get
0x0000000104204240 ==> 1 : Int
0x00007ffeefbff440 ==> 1 : Int
Why their addresses are different?
Here
print(unsafePointer: array)
a pointer to the first element of the array storage is passed to the function. And here
print(unsafePointer: &array[0])
the subscript operator is called on the array (returning an Int) and the address of that (temporary) integer is passed to the function, not the address where the original array element is stored.
That becomes more obvious if you call the functions twice:
var array = [1, 2, 3, 4]
print(unsafePointer: array) // 0x00007ffeefbff2e0
print(unsafePointer: array) // 0x00007ffeefbff2e0, same as previous address
print(unsafePointer: &array[0]) // 0x00007ffeefbff320
print(unsafePointer: &array[0]) // 0x00007ffeefbff340, different from previous address
In addition, passing an in-out expression to a function can make a temporary copy, see for example Swift: always copies on inout?.
Arrays in Swift have value semantics, not the reference semantics of arrays in C or Objective-C. The reason you're seeing different addresses (and addresses at all) is that every time you pass the array as a parameter, you're actually telling Swift to bridge your Array struct to an instance of NSArray.

Gets elements from 3 dimensional array

I'm new in Swift and do not know everything , i have this kind of an array
var arrayOFJumpForwardBack: [Int: [String: [String]]] =
[1: ["chapter": ["15 sec","30 sec","45 sec","60 sec"]]]
and , i'd like to know how can i get certain elements from this array?
Swift - Arrays & Dictionaries
The syntax of an array is as follows:
["value1","value2","value3"]
The syntax of a dictionary is as follows:
["ABC":"valueForABC","XYZ":"valueForXYZ"]
In this case you're using a dictionary, and the main difference with the array is that the order doesn't matter, each value is represented with a key, so with the following example:
Example:
Let's say we have a dictionary where we have stored the word "apple" whose key is "JHC" and "pear" whose key is "IOP". We want to print "I have an apple", then:
var myFridge:[String:String] = ["JHC":"apple","IOP":"pear"]
print("I have an \(myFridge["JHC"]!)")
A multidimensional array is just an array inside of another, x dimensions you want.
I'd rather prever to create a dictionary as above ↑

Can't mutate [Int] using .remove(at:)

var bigNum = [2,34,5].remove(at: 2)
Error:
Playground execution failed: error: CalculatorPlayGround.playground:35:14: error: cannot use mutating member on immutable value of type '[Int]'
var bigNum = [2,34,5].remove(at: 2)
But
var bigNum = [2,34,5]
var b = bigNum.remove(at: 2)
is ok.
What is the difference? Why does it work in the second case?
.remove(at:) tries to mutate the array you call it on.
When you create the array like you did in your first example ([1,2,3].whatever), it creates an immutable constant, as if you were to create it like this:
let array = [2, 34, 5] //not mutable
If you force it to create the array as a variable, it is mutable:
var array = [2, 34, 5] //mutable
Note
I don't know exactly what you are trying to do, but bigNum makes me assume you're trying to get a number from the array? Because right now, bigNum would become this array: [2, 34] instead of just a number.
[2,34,5] in itself is a literal, and as such is immutable in Swift (i.e. you can't write [2,34,5].remove(at: 2)). To apply a mutating function, you first need to store your array in a mutable container, using the var keyword:
var bigNum = [2,34,5]
Only after doing so, you can use mutating func .remove(at:) on mutable bigNum.

What does Array as Object mean in Basic4Android?

SQL1.ExecNonQuery2("INSERT INTO table1 VALUES(?,?,?)",Array As Object("def",3,4))
I don't seem to understand why the argument list in the above statement is declared in the form of Array as Object('xx','xx''xx').How is it exactly being converted into a list parameter ?
Array As xxx is a shorthand syntax for declaring a new array and assigning the values.
Array As Object("def", 3, 4)
Is equivalent to:
Dim arr As Object(3)
arr(0) = "def" : arr(1) = 3 : arr(1) = 4
Basic4android automatically wraps arrays as lists when needed. The items are not copied, it is the whole array that is wrapped in a list. Therefore the above code is valid as it creates an array which is then wrapped as a List.