Using arrays in Swift - arrays

Just started using Swift and I'm getting pissed at a few elements. First is that most standard stuff are structs rather than objects, which means they're passed in as values rather than pointers as I'm used to. The other thing is that using the optional element system is really annoying.
If I am trying to declare an array without putting anything in it, I declare it like this:
var theArray : [Int]
In order to put anything in it, I would declare it like this:
var theArray : [Int]?
Then add objects as follows:
theArray[someIndex] = someInt
//or
theArray.append(someInt)
However, I get an error. In Java, I could have just initialized an array with a length, which would have given me an a fixed-size array with all 0's.
The problem, summarized in a sentence, is adding elements to Swift arrays that have been initialized without values. How do you do this?

In order to initialize an empty array use:
var theArray : [Int] = []
then add elements by using append method. What you currently did is that you just declared it in the first case non optional and in the second case as an optional variable typed as int array without initializing it.

If you want the array to contain Int types, of course there are many ways to declare that, based on implicit or explicit type inference. These are all valid declarations of an array containing Int types
var array1 = [Int]()
var array2: [Int] = []
var array3 = Array<Int>()
var array4: Array<Int> = []
If you want an array of a certain size, with the values initialized to a certain value you can use, in this example you'll get an Array<Int> with 5 elements, all initialised to 0
var array = Array(count: 5, repeatedValue: Int(0))

Here you go:
var theArray = Array(count:[the length you want], repeatedValue:Int(0))
This will replicate the Java behaviour.

Related

Store value in an array

I am fairly new to Go. I have coded in JavaScript where I could do this:
var x = [];
x[0] = 1;
This would work fine. But in Go, I am trying to implement the same thing with Go syntax. But that doesn't help. I need to have a array with unspecified index number.
I did this:
var x []string
x[0] = "name"
How do I accomplish that?
When you type:
var x []string
You create a slice, which is similar to an array in Javascript. But unlike Javascript, a slice has a set length and capacity. In this case, you get a nil slice which has the length and capacity of 0.
A few examples of how you can do it:
x := []string{"name"} // Creates a slice with length 1
y := make([]string, 10) // Creates a slice with length 10
y[0] = "name" // Set the first index to "name". The remaining 9 will be ""
var z []string // Create an empty nil slice
z = append(z, "name") // Appends "name" to the slice, creating a new slice if required
More indepth reading about slices:
Go slices usage and internals
In JavaScript arrays are dynamic in the sense that if you set the element of an array using an index which is greater than or equal to its length (current number of elements), the array will be automatically extended to have the required size to set the element (so the index you use will become the array's new length).
Arrays and slices in Go are not that dynamic. When setting elements of an array or slice, you use an index expression to designate the element you want to set. In Go you can only use index values that are in range, which means the index value must be 0 <= index < length.
In your code:
var x []string
x[0] = "name"
The first line declares a variable named x of type []string. This is a slice, and its value will be nil (the zero value of all slice types, because you did not provide an initialization value). It will have a length of 0, so the index value 0 is out of range as it is not less that the length.
If you know the length in advance, create your array or slice with that, e.g.:
var arr [3]string // An array with length of 3
var sli = make([]string, 3) // A slice with length of 3
After the above declarations, you can refer to (read or write) values at indicies 0, 1, and 2.
You may also use a composite literal to create and initialize the array or slice in one step, e.g.
var arr = [3]string{"one", "two", "three"} // Array
var sli = []string{"one", "two", "three"} // Slice
You can also use the builtin append() function to add a new element to the end of a slice. The append() function allocates a new, bigger array/slice under the hood if needed. You also need to assign the return value of append():
var x []string
x = append(x, "name")
If you want dynamic "arrays" similar to arrays of JavaScript, the map is a similar construct:
var x = map[int]string{}
x[0] = "name"
(But a map also needs initialization, in the above example I used a composite literal, but we could have also written var x = make(map[int]string).)
You may assign values to keys without having to declare the intent in prior. But know that maps are not slices or arrays, maps typically not hold values for contiguous ranges of index keys (but may do so), and maps do not maintain key or insertion order. See Why can't Go iterate maps in insertion order? for details.
Must read blog post about arrays and slices: Go Slices: usage and internals
Recommended questions / answers for a better understanding:
Why have arrays in Go?
How do I initialize an array without using a for loop in Go?
How do I find the size of the array in go
Keyed items in golang array initialization
Are golang slices pass by value?
Can you please use var x [length]string; (where length is size of the array you want) instead of var x []string; ?
In Go defining a variable like var x=[]int creates a slice of type integer. Slices are dynamic and when you want to add an integer to the slice, you have to append it like x = append(x, 1) (or x = append(x, 2, 3, 4) for multiple).
As srxf mentioned, have you done the Go tour? There is a page about slices.
I found out that the way to do it is through a dynamic array. Like this
type mytype struct {
a string
}
func main() {
a := []mytype{mytype{"name1"}}
a = append(a, mytype{"name 2"})
fmt.Println(a);
}
golang playground link: https://play.golang.org/p/owPHdQ6Y6e

can you declare an empty array, without knowing the type in swift

for example:
let myArray:[] = []
or
let myArray = []
The first one is not possible (it will complain about expected element type) If you don't know the element type you can use AnyObject but if you know the type of it you have to put it there (Int,Double,String, AnyObject, etc...).
var myArrayOfDoubles:[Double] = []
The second one (when omitting the type) is OK ONLY if you initialize it with some values but If you try it with an empty array you won't be able to append anything (at least using Playground) saying that NSArray does not have a member named append.
var myArrayOfInts = [1,2,3,4,5] // [Int]
var myArrayOfAnyObject:[AnyObject] = [] // [AnyObject]
And finally last but not least you have to define it as var because if you define it using let it will stay empty forever :)
Yes, you can, it can be Any or Anyobject...
example:
var noTypeArray = [Any]()
If you want to fill the array eventually it may be var, no let, there's no point otherwise.
No. If you don't know what will go in use this:
var myArray = [Any]()
Apple has introduced a Type-GeStaPo and you must type anything that's not up the tree at count three.
To add to this use
myArray.append("this")
myArray.append(1)
myArray.append(myObject)

Cannot assign to "" in "self" - Working with Tuples in Swift

I have to classes: FirstViewController and PlanGenerator.
PlanGenerator has a method called getPlanForIndex (day:Int) -> ([PlanElement], [PlanElement])?. It is returning two different Arrays, both containing Object of Plan Element.
getPlanForIndex (day:Int) -> ([PlanElement], [PlanElement])? {
// Do some work and fill arrays
return (firstArray, secondArray)
}
In the FirstViewController I've created two Properties:
let plan:[PlanElement] = [PlanElement]()
let planGen:PlanGenerator = PlanGenerator()
FirstViewControllerhas a method called:
func prepareView () {
plan = planGen.getPlanForIndex(dayIndex)
}
But when I want to call this, I get the error message:
Cannot assign to 'plan' in 'self'
First, your plan member is a constant (declared with let), and you're assigning to it outside of init. If you want to assign to it after initialization, it needs to be declared with var.
Also, your getPlanForIndex returns a tuple, and you're assigning it to a member of singular (not tuple) type. If you want to assign one part of a tuple only, do it like this:
(plan, _) = planGen.getPlanForIndex(dayIndex)
That assigns a tuple to a tuple, satisfying the compiler, but discards the second element.
If you instead want plan to be a tuple, you'll have to declare and initialize it as such. Looks from the comments like you figured out a way to do that, but here's a way with minimal typing (in either sense of the word):
var plan: ([PlanElement], [PlanElement]) = ([], [])
(Once you've declared the type of array, [] is understood to be an empty array of that type. Just var plan = ([], []) leaves the type ambiguous.)

Add value to empty Swift array

I cannot figure out how to add values to an empty array in Swift. I have tried started with empty array in two different ways:
var emptyArray : Int[]?
emptyArray = Int[]()
and
var emptyArray = []
(by the way, what is the difference with these two ways of creating empty arrays?)
I have tried to add an integer to the array with emptyArray.append(1), emptyArray += [1] but none works nor it is in the guide book (or maybe, it is hidden some where that I couldn't figure out). Both of these work if there is one or more values in it and this is driving me crazy! Please let me know how to if you know how to do it. Thank you!
First, create empty Int array:
var emptyArray : Int[] = []
or:
var emptyArray = Int[]()
Add number to that array (two ways):
emptyArray += [1]
emptyArray.append(2)
Array now contains [1, 2]
You need to first declare the empty array in Swift like this:
var emptyArray = [Int]()
You can then append that array with whatever value/variable you so choose like this:
emptyArray.append(6)
just be sure you keep in mind that trying to append a type that mismatches your array declaration will give you a compile error. For example, trying to append a string would error since this array was declared using the Int type.
Playgrounds in XCode are an excellent resource for testing things like this.
Swift
var arrName = [String]()
arrName = ["Deep", "Hemant", "Yash"]
print("old array--> ", arrName)
arrName.append("Jay")
print("new array--> ", arrName)
Output:-
old array--> ["Deep", "Hemant", "Yash"]
new array--> ["Deep", "Hemant", "Yash", "Jay"]

IndexOf() not working

In ActionScript 3, it seems like indexOf is not working when I try to find something like [int, int].
For example:
var array:Array = new Array();
array.push([5, 6]);
trace(array.indexOf([5, 6])); //-1
I wonder if I'm missing something here.
Arrays, like all non-primitive types in AS3, are checked by reference, not by value. Whenever you create a new instance of an object (like an array), the variable is actually a pointer to a location in memory where the object resides.
For this reason, your code won't work because you're comparing pointers to two different arrays. The language doesn't know (or care) about the contents of the objects, all it's looking to compare are the memory locations (ie the reference) to the two objects.
If we look at your code:
var array:Array = new Array();/
array.push([5, 6]);
trace(array.indexOf([5, 6])); //-1
You are actually declaring three different arrays, each with its own location in memory. Firs you create the array var, onto this you push a new array, and in this you then try to search for a new array (in indexOf([5, 6]) you are declaring a new array in-line). For this reason the search returns false, because the references do not match - even if the contents of the arrays do.
var array:Array = new Array();
var subArray:Array = [5, 6];
array.push(subArray);
trace(array.indexOf(subArray)); // 0
...this works because the reference to the array matches.
Primitive types - Numeric, Boolean, String, are compared by value eg
var a:int = 10; var b:int = 10; trace(a == b);//True
where reference types are not:
var a:Array = [5]; var b:Array = [5]; trace(a == b);//False
It would be time-consuming for the player to compare all properties of two different objects before declaring them 'equal' or not (as most complex data types do not have a distinct 'value' in the same way that a number does), so for anything non-primitive, lookups and comparisons are done by reference.
Hope this helps.
Everytime you write [5, 6] you are creating a new instance of [int, int]. When doing indexOf() and comparing objects, it only checks if that particular instance exists (by checking for a reference to the object) in the array, not another instance with the same values. You could change your code as follows for it it work as expected:
var arr0:Array = [5, 6];
var array:Array = new Array();
array.push(arr0);
trace(array.indexOf(arr0)); //should print 0 now instead of -1

Resources