I'm new to Swift and is trying to learn its syntax. I saw this code online.
var items = [Int]()
I know
var = declaring a variable
items = the name of the variable is 'items'
[Int] = array of Int
However, I'm not sure the purpose of the () after [Int]. I know the code wouldn't compile without the (), but what is its purpose?
It is initializing a new instance of an Array that will contain Ints. It is a shorthand of this syntax:
var items = Array<Int>()
Instead of Array<Int> for the type you can use [Int] instead.
A third variation would be to explicitly state the type, and then assign an empty array.
var items: [Int] = []
Related
I want to initialize my Empty Array with some data, however the array does not accept new data, It must be easy thing, but I do not know what I am missing!
var arrayOfString: [String]?
arrayOfString?.append( "New Data"); print( "\(arrayOfString?.count)" )
Initializing means to assign a default value
var arrayOfString: [String]? = []
But in almost all cases collection types can be declared (and initialized) non-optional
var arrayOfString = [String]()
var someDict = [String:Any]()
someDict["foo"] = ["hello"]
(someDict["foo"] as? [String])?.append("goodbye") // error here
I am trying to add a value to an existing dictionary containing an array. The dictionary also contains other non-array values, so it has to have value type Any. The problem is that, when I do this, I get an error Cannot use mutating member on immutable value of type '[String]'. Some Googling turned up a few references such as this suggesting that arrays within dictionaries are always immutable, but the compiler doesn't complain if I do this:
var someDict = [String:[String]]()
someDict["foo"] = ["hello"]
someDict["foo"]?.append("goodbye")
so I suspect that information is outdated and it's something specific to the downcasting. Is there any way I can get around this without copying and re-assigning the entire dictionary value?
Yes, it is related the the downcasting. Try this instead:
var someDict = [String:Any]()
someDict["foo"] = ["hello"]
if var arr = someDict["foo"] as? [String] {
arr.append("goodbye")
someDict["foo"] = arr
}
I have the following code that attempts to consolidate redundant elements of an array:
var items : [String] = ["hello", "world", "!", "hello"]
var mutableSet = Set<String>()
items.reduce(mutableSet, combine: { (set: Set<String>, element: String) in
return set.insert(element)
})
set.insert(element) gives me the error Cannot use mutating member on immutable value: 'set' is a 'let' constant. What's wrong and how can I fix it?
The problem with the OP's code is that the accumulator in the reduce is immutable so it won't allow you to use the mutating function insert().
A tidy solution is to define an non-mutating equivalent to insert() called inserting() in an extension to Set as follows.
extension Set {
//returns a new set with the element inserted
func inserting(_ element: Element) -> Set<Element> {
var set = self
set.insert(element)
return set
}
}
Now we can write the reduce as follows
var items : [String] = ["hello", "world", "!", "hello"]
let set = items.reduce(Set<String>()){ accumulator, element in
accumulator.inserting(element)
}
In Swift, collections are value types. Value-typed variables declared with let (as implicitly are function parameters) cannot be modified. Additionally, your closure returns nothing, so reduce will probably not succeed.
I believe that reduce is not the best-suited tool for this task. Consider this for loop instead:
var set = Set<String>()
for element in items { set.insert(element) }
Another even simpler option would be to use the unionInPlace method:
var set = Set<String>()
set.unionInPlace(items)
Even better perhaps, create the set straight from the collection:
var set = Set<String>(items)
The 'set' value returned is a constant. This is important as it is the accumulator, which represents the values that have accumulated, thus far. It should not change in your closure.
Here is an example from a project I'm working on at the moment, where I want to find all of the unique performers, across many theatrical performances. Notice how I am using union, which does not modify the constant value 'performers', but instead consumes it to produce a new value.
let uniquePerformers = performances.reduce(Set<Performer>(), { (performers: Set<Performer>, performance) -> Set<Performer> in
return performers.union(Set(performance.performers))
})
I am quite a confused when and how to declare variables in particular points in Swift and its causing a headache for a new guy like me in SWIFT.
What is the difference between the following type of declarations? I have given my thoughts and understanding on them. Please rectify me with your solution if I am wrong and be a bit explanatory so that I can know the actual and exact answer.
Array -
1) var arr = NSArray()//I think its an instance of immutable NSArray type
2) var arr = NSMutableArray()
3) var arr = Array()//I have no idea of difference between NSArray and Array type. Might be both are same
4) var arr : NSMutableArray?//Creates an optional type but how is it different from line no.2
5) var arr : NSMutableArray = []//creates an empty array NSMutableArray type and again how is it different from line no.2 & 3
Please clarify a bit clearly so that my confusion level would be a bit clear. Thanks
Array is a swift type where as NSArray is an objective C type. NS classes support dynamic-dispatch and technically are slightly slower to access than pure swift classes.
1) var arr = NSArray()
arr is an NSArray() here - you can re-assign things to arr but you can't change the contents of the NSArray() - this is a bad choice to use IMO because you've put an unusable array into the variable. I really can't think of a reason you would want to make this call.
2) var arr = NSMutableArray()
Here you have something usable. because the array is mutable you can add and remove items from it
3) var arr = Array()
This won't compile - but var arr = Array<Int>() will.
Array takes a generic element type ( as seen below)
public struct Array<Element> : CollectionType, MutableCollectionType, _DestructorSafeContainer {
/// Always zero, which is the index of the first element when non-empty.
public var startIndex: Int { get }
/// A "past-the-end" element index; the successor of the last valid
/// subscript argument.
public var endIndex: Int { get }
public subscript (index: Int) -> Element
public subscript (subRange: Range<Int>) -> ArraySlice<Element>
}
4) var arr : NSMutableArray?
You are defining an optional array here. This means that arr starts out with a value of nil and you an assign an array to it if you want later - or just keep it as nil. The advantage here is that in your class/struct you won't actually have to set a value for arr in your initializer
5) var arr : NSMutableArray = []
It sounds like you are hung up on confusion about Optional values.
Optional means it could be nil or it could not
When you type something as type? that means it is nil unless you assign it something, and as such you have to unwrap it to access the values and work with it.
#G.Abhisek at first about you question. var arr: NSMutableArray = [] and var arr = NSMutableArray() means the same. the first one means, i ask the compiler to create a variable of type NSMutableArray and initialize it as an empty NSMutableArray. the second one means, i ask the compiler to create a variable and assign to it an empty initialized NSMutableArray. in the second case the compiler has to infer the right type of the variable, in the first case i did it by myself. still, the result will be the same. var arr1: Array<AnyObject> = [] and var arr2: NSMutableArray = [] are totally different things!. arr1 srores value type Array, arr2 stores reference to the instance of an empty NSMutableArray class. you can write let arr2: NSMutableArray = [] and next you can add an object there ... but you are not able to do thinks like arr2 = ["a","b"]. arr2 is constant, not variable, so the value stored there is imutable.
i am again close to my computer ... in the code below, you can see the main differences between swift and foundation arrays
import Foundation
let arr1: NSMutableArray = []
arr1.addObject("a")
arr1.addObject(10)
arr1.forEach {
print($0, $0.dynamicType)
/*
a _NSContiguousString
10 __NSCFNumber
*/
}
var arr2: Array<Any> = []
arr2.append("a")
arr2.append(10)
arr2.forEach {
print($0, $0.dynamicType)
/*
a String
10 Int
*/
}
var arr3: Array<AnyObject> = []
arr3.append("a")
arr3.append(10)
arr3.forEach {
print($0, $0.dynamicType)
/*
a _NSContiguousString
10 __NSCFNumber
*/
}
print(arr1.dynamicType, arr2.dynamicType, arr3.dynamicType)
// __NSArrayM Array<protocol<>> Array<AnyObject>
I looked through docs some forums and found I can create an array in various ways. I am confused which one should we be using?
var testArray = [Int]()
testArray.append(1)
var anotherTestArray: [Int] = []
anotherTestArray.append(1)
var yetAnotherTestArray: Array<Int> = []
yetAnotherTestArray.append(1)
var yetYetYetAnotherTestArray = Array<Int>()
yetYetYetAnotherTestArray.append(1)
This is not empty array but It keeps it's type for each element to be strictly to an Int
var yetYetAnotherTestArray = [1]
I think the cleanest way to create an array is var testArray: [Int] = []
In swift array objects must be the same type. If you want to store different objects of different types use [AnyObject]. However, you should always know what is coming out of it. Since the returning type value will be AnyObject, you have to cast down the value to the type you want.
I really don't recommend using AnyObject as the type of your arrays unless you really know what you are doing.
Here is an example anyway:
let a: [AnyObject] = [1, "a"]
let b = a[0] // An Int
let c = a[1] // A String