## Overview

- An unordered collection of unique elements.
- You use a set instead of an array when you need to test efficiently for membership and you aren’t concerned with the order of the elements in the collection, or when you need to ensure that each element appears only once in a collection.
- Swift makes it as easy to create a new set as to create a new array. Simply assign an array literal to a variable or constant with the Set type specified.

## 1. Creating a Set

#### 1.1 init()

- Creates an empty set.

```
var emptySet = Set<Int>()
print(emptySet.isEmpty)
// Prints "true"
emptySet = []
print(emptySet.isEmpty)
// Prints "true"
```

#### 1.2 init(minimumCapacity:)

- Creates a new, empty set with at least the specified number of elements’ worth of buffer.

```
var emptySetWithCapacity = Set<Int>(minimumCapacity: 10)
print(emptySetWithCapacity)
//prints []
```

#### 1.3 init(_:)

- Creates a new set from a finite sequence of items.

```
let validIndices = Set(0..<7).subtracting([2, 4, 5])
print(validIndices)
// Prints [6, 0, 1, 3]
```

## 2. Inspecting a Set

#### 2.1 isEmpty

- A Boolean value that indicates whether the set has no elements.

```
var emptySet = Set<Int>()
print(emptySet.isEmpty)
// Prints "true"
```

#### 2.2 count

- The number of elements in the collection.

```
let validIndices = Set(0..<7).subtracting([2, 4, 5])
print(validIndices.count)
//prints 4
```

#### 2.3 first

- The first element of the collection.

```
let numbers = [10, 20, 30, 40, 50]
if let firstNumber = numbers.first {
print(firstNumber)
}
//prints 10
```

#### 2.4 capacity

- The total number of elements that the set can contain without allocating new storage.

```
let validIndices = Set(0..<7).subtracting([2, 4, 5])
print(validIndices.capacity)
//prints 12
```

## 3. Testing for Membership - contains(_:)

- Returns a Boolean value that indicates whether the given element exists in the set.

```
if (validIndices.contains(3)){
print("value is there in set")
}
//prints value is there in set
```

## 4. Adding Elements

#### 4.1 insert(_:)

- Inserts the given element in the set if it is not already present.

```
enum DayOfTheWeek: Int {
case sunday, monday, tuesday, wednesday, thursday,
friday, saturday
}
var classDays: Set<DayOfTheWeek> = [.wednesday, .friday]
print(classDays.insert(.monday))
print(classDays)
//prints (inserted: true, memberAfterInsert: //TempCode.DayOfTheWeek.monday)
//[TempCode.DayOfTheWeek.friday, //TempCode.DayOfTheWeek.wednesday, //TempCode.DayOfTheWeek.monday]
```

#### 4.2 update(with:)

- Inserts the given element into the set unconditionally.

```
print(classDays.update(with: .monday) ?? "Default")
//prints monday
```

## 5. Removing Elements

#### 5.1 filter(_:)

- Returns a new set containing the elements of the set that satisfy the given predicate.

```
let cast: Set = ["Vivien", "Marlon", "Kim", "Karl"]
let shortNames = cast.filter { $0.count < 5 }
print(shortNames)
// ["Karl", "Kim"]
print(shortNames.contains("Vivien"))
// prints false
```

#### 5.2 remove(_:)

- Removes the specified element from the set.

```
var ingredients: Set = ["cocoa beans", "sugar", "cocoa butter", "salt"]
let toRemove = "sugar"
if let removed = ingredients.remove(toRemove) {
print("The recipe is now \(removed)-free.")
}
//prints The recipe is now sugar-free.
```

#### 5.3 removeFirst()

- Removes the first element of the set.

```
var ingredients: Set = ["cocoa butter", "sugar", "cocoa beans", "salt"]
print("set removes \(ingredients.removeFirst())")
//prints set removes cocoa butter
```

#### 5.4 removeAll(keepingCapacity:)

- Removes all members from the set.

```
ingredients.removeAll(keepingCapacity: false)
print(ingredients)
//prints []
```

## 6. Combining Sets

#### 6.1 union(_:)

- Returns a new set with the elements of both this set and the given sequence.

```
let attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Marcia", "Nathaniel"]
let attendeesAndVisitors = attendees.union(visitors)
print(attendeesAndVisitors)
//prints ["Alicia", "Diana", "Bethany", "Marcia", "Nathaniel"]
```

#### 6.2 formUnion(_:)

- Inserts the elements of the given sequence into the set.

```
let attendees: Set = ["Alicia", "Bethany", "Diana"]
let visitors = ["Marcia", "Nathaniel"]
attendees.formUnion(visitors)
print(attendees)
//prints ["Alicia", "Diana", "Bethany", "Marcia", "Nathaniel"]
```

#### 6.3 intersection(_:)

- Returns a new set with the elements that are common to both this set and the given sequence.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
let bothNeighborsAndEmployees = employees.intersection(neighbors)
print(bothNeighborsAndEmployees)
//prints ["Bethany", "Eric"]
```

#### 6.4 formIntersection(_:)

- Removes the elements of the set that aren’t also in the given sequence.

```
var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let neighbors = ["Bethany", "Eric", "Forlani", "Greta"]
employees.formIntersection(neighbors)
print(employees)
// Prints ["Bethany", "Eric"]
```

#### 6.5 symmetricDifference(_:)

- Returns a new set with the elements that are either in this set or in the given sequence, but not in both.

```
let employees: Set = ["Alicia", "Bethany", "Diana", "Eric"]
let neighbors = ["Bethany", "Eric", "Forlani"]
let eitherNeighborsOrEmployees = employees.symmetricDifference(neighbors)
print(eitherNeighborsOrEmployees)
// Prints ["Diana", "Forlani", "Alicia"]
```

#### 6.6 formSymmetricDifference(_:)

- Removes the elements of the set that are also in the given sequence and adds the members of the sequence that are not already in the set.

```
var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
employees.formSymmetricDifference(neighbors)
print(employees)
// Prints ["Diana", "Chris", "Forlani", "Alicia", "Greta"]
```

#### 6.7 subtract(_:)

- Removes the elements of the given set from this set.

```
var employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
employees.subtract(neighbors)
print(employees)
// Prints ["Diana", "Chris", "Alicia"]
```

#### 6.8 subtracting(_:)

- Returns a new set containing the elements of this set that do not occur in the given set.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let neighbors: Set = ["Bethany", "Eric", "Forlani", "Greta"]
let nonNeighbors = employees.subtracting(neighbors)
print(nonNeighbors)
// Prints ["Diana", "Chris", "Alicia"]
```

## 7. Comparing Sets

#### 7.1 ==(*:*:)

- Returns a Boolean value indicating whether two sets have equal elements.

```
if(employees == neighbors){
print("All neighbours work together ")
}else{
print ("set din't match")
}
//prints set din't match
```

#### 7.2 !=(*:*:)

- Returns a Boolean value indicating whether two values are not equal.

```
if(employees != neighbors){
print("All employees do not live together ")
}else{
print ("employees are neighbours")
}
//prints All employees do not live together
```

#### 7.3 isSubset(of:)

- Returns a Boolean value that indicates whether this set is a subset of the given set.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let attendees: Set = ["Alicia", "Bethany", "Diana"]
print(attendees.isSubset(of: employees))
//prints true
```

#### 7.4 isStrictSubset(of:)

- Returns a Boolean value that indicates whether the set is a strict subset of the given sequence.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let attendees: Set = ["Alicia", "Bethany", "Diana"]
print(attendees.isStrictSubset(of: employees))
// Prints true
```

#### 7.5 isSuperset(of:)

- Returns a Boolean value that indicates whether this set is a superset of the given set.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let attendees: Set = ["Alicia", "Bethany", "Diana"]
print(employees.isSuperset(of: attendees))
// Prints true
```

#### 7.6 isStrictSuperset(of:)

- Returns a Boolean value that indicates whether the set is a strict superset of the given sequence.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let attendees: Set = ["Alicia", "Bethany", "Diana"]
print(employees.isStrictSuperset(of: attendees))
// Prints true
```

#### 7.7 isDisjoint(with:)

- Returns a Boolean value that indicates whether this set has no members in common with the given set.

```
let employees: Set = ["Alicia", "Bethany", "Chris", "Diana", "Eric"]
let visitors: Set = ["Marcia", "Nathaniel", "Olivia"]
print(employees.isDisjoint(with: visitors))
// Prints true
```

## 8. Finding Elements

#### 8.1contains(where:)

- Returns a Boolean value indicating whether the sequence contains an element that satisfies the given predicate.

```
enum HTTPResponse {
case ok
case error(Int)
}
let lastThreeResponses: [HTTPResponse] = [.ok, .ok, .error(404)]
let hadError = lastThreeResponses.contains { element in
if case .error = element {
return true
} else {
return false
}
}
print(hadError)
//prints true
```

#### 8.2 first(where:)

- Returns the first element of the sequence that satisfies the given predicate.

```
var numbers = [3, 7, 4, -2, 9, -6, 10, 1]
if let firstNegative = numbers.first(where: { $0 < 0 }) {
print("The first negative number is \(firstNegative).")
}
//prints The first negative number is -2.
```

#### 8.3 index(of:)

- Returns the index of the given element in the set, or nil if the element is not a member of the set.

```
var numbers = [3, 7, 4, -2, 9, -6, 10, 1]
print(numbers.index(of: 4) ?? "default")
//prints 2
```

#### 8.4 min(_:)

- Returns the minimum element in the sequence.

```
let heights = [67.5, 65.7, 64.3, 61.1, 58.5, 60.3, 64.9]
let lowestHeight = heights.min()
print(lowestHeight ?? "defaultValue")
//prints 58.5
```

#### 8.5 min(by:)

- Returns the minimum element in the sequence, using the given predicate as the comparison between elements.

```
let hues = ["Heliotrope": 296, "Coral": 16, "Aquamarine": 156]
let leastHue = hues.min { a, b in a.value < b.value }
print(leastHue ?? "defaultvalue")
//prints (key: "Coral", value: 16)
```

#### 8.6 max(_:)

- Returns the maximum element in the sequence.

```
let greatestHeight = heights.max()
print(greatestHeight ?? "default")
//prints 67.5
```

#### 8.7 max(by:)

- Returns the maximum element in the sequence, using the given predicate as the comparison between elements.

```
let greatestHue = hues.max { a, b in a.value < b.value }
print(greatestHue ?? "defaultValue")
//prints (key: "Heliotrope", value: 296)
```

## 9. Iterating over a Set

#### 9.1 enumerated()

- Returns a sequence of pairs (n, x), where n represents a consecutive integer starting at zero, and x represents an element of the sequence.

```
for (n, c) in "Swift".enumerated() {
print("\(n): '\(c)'")
}
//prints 0: 'S'
// 1: 'w'
// 2: 'i'
// 3: 'f'
// 4: 't'
```

#### 9.2 forEach(_:)

- Calls the given closure on each element in the sequence in the same order as a for-in loop.

```
let numberWords = ["one", "two", "three"]
for word in numberWords {
print(word)
}
//prints one
// two
// three
numberWords.forEach { word in
print(word)
}
//prints one
// two
// three
```

## 10. Describing a Set

#### 10.1 description

- A string that represents the contents of the set.

```
var numberWord : Set = ["one", "two", "three", "one"]
print(numberWord.description)
//["two", "one", "three"]
```

#### 10.2 debugDescription

- A string that represents the contents of the set, suitable for debugging.

```
var numberWord : Set = ["one", "two", "three", "one"]
print(numberWord.debugDescription)
//prints Set(["two", "three", "one"])
```

#### 10.3 customMirror

- A mirror that reflects the set.

```
var numberWord : Set = ["one", "two", "three", "one"]
print(numberWord.customMirror)
//prints Mirror for Set<String>
```

#### 10.4 hashValue

- The hash value for the set.

```
var numberWord : Set = ["one", "two", "three", "one"]
print(numberWord.hashValue)
//prints 1208559987431737550
```

**Next** - Dictionary by Example