Swift - Declaring a Set using named variable - swift

I am trying to understand Sets in Swift and how to declare them correctly but I have found the following a little confusing.
I understand that this works:
let elements = [ 1, 2, 3, 4, 5, 1, 2, 6, 7]
let setFromElements = Set(elements)
But I don't understand why the following doesn't:
let setFromElements : Set = elements
Or even:
let setFromElements : Set<Int> = elements
When the following is valid:
let setFromArray : Set = [ 1, 2, 4, 5]
Can someone please help me understand why this is the case?

let setFromArray: Set = [ 1, 2, 4, 5] works because Set conforms to ExpressibleByArrayLiteral and hence has an initializer that takes an ArrayLiteral. See Set.init(arrayLiteral:). This conformance gives syntactic sugar for not having to explicitly call the init.
On the other hand, once you save the array literal into a variable using let elements = [ 1, 2, 3, 4, 5, 1, 2, 6, 7], elements becomes an Array, not an ArrayLiteral and hence another initializer of Set has to be called that takes an Array. This init does not provide syntactic sugar like ExpressibleByArrayLiteral does, so you explicitly have to call the init by doing Set(array).

Set has an initializer that takes an array, and that makes a set, by taking the unique items in the array. But a set is not an array, two different types, so you can't just use = to assign one to the other.

Related

How to replace slice of array in Swift?

To replace a slice of array in Swift, we can use subscript assignment or replaceSubrange method on array. But, I wonder how can I change the elements of named subrange so that original array change as well?
var array = Array(0..<10)
var slice = array[0..<3]
slice[...] = [-1,-1,-1]
print(slice) // [-1, -1, -1]
print(array) // [0, 1, 2, 3, 4, 5, 6, 7, 8, 9] does not change

Trying to access some elements in an IndexSet

I'm using IndexSet and I'm trying to access some indexes which at times are consecutive and at other times are not.
For example, my set may contain [1, 2, 3, 5, 6, 7, 13, 31]
I want to pull out of the set a range of 3...13, but am having difficulty with the syntax. I've learned how to use the function commands from Apple documentation, by using myIndexSet.sorted(). However, the Apple Documentation does not give an example of how to access a range of elements in the set. The Apple Documentation for accessing elements in the index set are the following:
subscript(Range<IndexSet.Index>)
I've tried a number of ways to write this but can't figure out how to do it right. Can someone show me how to access a range of elements in the set to create a new set? I've tried things such as:
let subset = subscript(Range: myLargerSet.3...13)
but it doesn't seem to work.
Thanks
What you're looking for is the intersection of your IndexSet ([1, 2, 3, 5, 6, 7, 13, 31]) with another IndexSet ([3, 4, ..., 12, 13]):
let yourIndexSet: IndexSet = [1, 2, 3, 5, 6, 7, 13, 31]
let desiredIndexRange = IndexSet(3...13)
let indicesOfInterest = yourIndexSet.intersection(desiredIndexRange)
print(indicesOfInterest.sorted()) // => [3, 5, 6, 7, 13]
One possible solution is to use a filter to create a new IndexSet.
let set = IndexSet(arrayLiteral: 1,2,3,5,6,7,13,31)
let subset = set.filteredIndexSet { (index) -> Bool in
index >= 3 && index <= 13
}
You can access a slice of your original set as follows:
let slice = indexSet[indexSet.indexRange(in: 3...13)]
slice accesses the existing elements in place, so creation of the slice is O(1)

Swift: Set<Object> fundamental operations result in copies or pointers?

I'm currently looking for some reference, outside apple's swift programming reference for the memory space of Set types and resulting fundamental operations (union, intersection, exclusion, subtraction etc)
Given the below pseudo code:
var entities = Set<GKEntity>()
var subSetA = Set<GKEntity>()
var subSetB = Set<GKEntity>()
Each subset will have a subclass of GKEntity which will be called on some routines I will use elswhere in my application.
When I use the union of these subsets, IE: I will have set as the superset of all subsets, or the union of all subsets.
Does this mean that the superset will be a copy of the elements in the subset or will they be pointers only?
I ask this for memory space usage as if the operation requires copying or allocating new memory adresses, I will need to use a different strategy of storing my elements.
From a purely structural standpoint, I assume these will be "shallow" copies meaning they will be pointers to memory adresses, but once I have created the superset as the union of all subsets, I want any removal or addition to be reflected on the superset, or down on the particular subset if the operation is made on the superset.
Hope this question is valid
Note, I'm assuming you mean this GKEntity.
Since GKEntity is a class, the sets you created will store references (pointers) to those actual GKEntity objects. So any changes to the objects in a subset will be reflected in the superset.
Here is a short piece of code that demonstrates this:
class A: IntegerLiteralConvertible, Hashable, CustomStringConvertible {
var x: Int
required init(integerLiteral value: Int) {
self.x = value
}
var hashValue: Int {
return x
}
var description: String {
return String(x)
}
}
func ==(lhs: A, rhs: A) -> Bool {
return lhs.hashValue == rhs.hashValue
}
let setA: Set<A> = [1, 2, 3, 4]
let setB: Set<A> = [5, 6, 7, 8]
print(setA) // [2, 3, 1, 4]
print(setB) // [5, 6, 7, 8]
let union = setA.union(setB)
print(union) // [2, 4, 5, 6, 7, 3, 1, 8]
setA.first!.x = 30
print(union) // [30, 4, 5, 6, 7, 3, 1, 8]
As you can see, I made a change (changed x from 2 to 30) to the first item in setA. Then I printed out union, which did contain a 30 in it.

What is wrong with this array filter call in Swift?

var arr = [4, 5, 23, 4, 5, 2, 3]
arr.filter({
return true
})
I get the error 'Int' is not a subtype of (). What am I doing wrong? Everything I've read seems to indicate this should work.
var arr = [4, 5, 23, 4, 5, 2, 3]
let arr2 = arr.filter {
_ in
return true
}
Problems with your original code:
filter returns an array. If you don't capture it, nothing useful happens. Notice that I've captured it in another variable; you could also reassign to the original variable.
If a parameter is passed into an anonymous function, you must capture it. You can capture it namelessly, as here, or with a name, or as $0, but you cannot completely ignore it; you must acknowledge it. That is what my _ in does.
You have to provide an index to the filter:
arr.filter({
n in true
})

How to add integer to array (with explicite int index) in swift?

I read swift handbook and was trying to do some exercises. But I run into a problem and I do not know if I do something wrong or if xCode 6 beta is just buggy.
// Playground - noun: a place where people can play
import Cocoa
let interestingNumbers = [
"Prime": [2, 3, 5, 7, 11, 13],
"Fibonacci": [1, 1, 2, 3, 5, 8],
"Square": [1, 4, 9, 16, 25],
]
var largest = 0
var lastLargest = Integer[]()
var index = 0
for (kind, numbers) in interestingNumbers {
for number in numbers {
if number > largest {
//lastLargest[index] = number
index++
largest = number
}
}
}
index
lastLargest
largest
As soon as I uncomment lastLargest[index] = number I do not get any results on right side in playground. Nor I get any infos about index, lastLargest or largest.
Following example does not work either:
var index2 = 0
var lastLargest2 = Integer[]()
lastLargest2[index2] = 1
index2++
lastLargest2[index2] = 2
You are appending using an out of bound array-index. Don't do that. Instead, use append:
lastLargest.append(number)
From Apple's documentation:
You can’t use subscript syntax to append a new item to the end of an array. If you try to use subscript syntax to retrieve or set a value for an index that is outside of an array’s existing bounds, you will trigger a runtime error.
When you're using explicit indexes (subscript notation) to set values in a mutable array, some value must already exist in that array at that index. When you use subscript notation, you're essentially using a 'set', rather than a 'set and add if necessary'.
As a result, you should be using:
lastLargest.insert(number, atIndex: index)
If you want to insert a new item. This will let you insert an item at the specified index, assuming your collection's size is already greater than or equal to the index you're trying to replace.