## Operating on a Sets in Python

A Set in Python is an unordered and unindexed collection of elements written within curly brackets. Sets are iterable and mutable. A set can never contain duplicate values. The repetition of items is not allowed in a set.

Various operations can be applied upon Python’s sets. These operations are possible using some Operators or Methods. However, only a few operations are possible by operators and methods both. It means some of these operations are possible with operators a few of them are possible by methods only.

For example, there are two sets, s1 and s2, the union of s1 and s2 results in a new set containing all the items in set s1 and s2.

```s1= {10, 20, 'sum', True}
s2={20, 30, 'sub', False}
s3=s1.union(s2)
print('Method', s3)
print('operator', s1 | s2)

#Output
Method {False, True, 'sub', 'sum', 10, 20, 30}
operator {False, True, 'sub', 'sum', 10, 20, 30}
```

### Union of Sets

As discussed in the above example, we can perform the union operation by union() method or Union operator ( | ). The minute difference between these two is that for the ( | ) operator the operands must be sets only, but in case of the method union(), an iterable(read iterator and iterable in Python) can be passed as an argument. It will be converted to a set automatically to perform the operation.

```s1= {10, 20, 'sum', True}
s2=(20, 30, 'sub', False)
s3=s1.union(s2)
print('Method', s3) # Works Fine
print('operator', s1 | s2) #ERROR
```

We can perform a union of multiple Sets together,

```a = {10, 20, 30, 40}
b = {20, 30, 40, 50}
c = {30, 40, 50, 60}
d = {40, 50, 60, 70}

print("Method", a.union(b, c, d)) #Method

print("Operator", a | b | c | d)  #Operator

#Output
Method {70, 40, 10, 50, 20, 60, 30}
Operator {70, 40, 10, 50, 20, 60, 30}
```

### Intersection of Sets

We can find the intersection of two sets using the method intersection() or the ( & ) operator. The intersection of sets results in a set containing the common values in the input sets.

For example,

```s1= {10, 20, 5, 'sum', True}
s2={20, 30, 5, 'sub', False}
s3=s1.intersection(s2)
print('Method', s3)  #intersection
print('Operator', s1 & s2) #intersection

#Output
Method {20, 5}
operator {20, 5}
```

Similar to union operation, the subtle difference between using intersection() method and ( & ) operator is that both the operands must be sets for using ( & ) operator but in case of the intersection() method the argument can be any iterable.

```s1= {10, 20, 5, 'sum', True}
s2=(20, 30, 5, 'sub', False)
s3=s1.intersection(s2)
print('Method', s3)  #intersection
print('Operator', s1 & s2) #ERROR

#Output
```

We can apply intersection operation on multiple sets using both techniques. For example,

```a = {10, 20, 30, 40}
b = {20, 30, 40, 50}
c = {30, 40, 50, 60}
d = {40, 50, 60, 70}

print("Method", a.intersection(b, c, d)) #Method

print("Operator", a & b & c & d)  #Operator

#Output

Method {40}
Operator {40}
```

### Difference of Sets

The difference of the sets can be computed using the difference() method or the ( - ) operator in Python. Let there be two sets s1 and s2, s1- s2 return the set of all elements that are inset s1 but not in s2.

For example,

```s1= {10, 20, 5, 'sum', True}
s2={20, 30, 5, 'sub', False}
s3=s1.difference(s2)
print('Method', s3)  #difference
print('Operator', s1 - s2) #differnce

#Output
Method {True, 10, 'sum'}
Operator {True, 10, 'sum'}
```

Similar to union operation, the subtle difference between using difference() method and ( - ) operator is that both the operands must be sets for using ( - ) operator but in case of the difference() method the argument can be any iterable.

```s1= {10, 20, 5, 'sum', True}
s2=(20, 30, 5, 'sub', False)
s3=s1.difference(s2)
print('Method', s3)  #difference
print('Operator', s1 - s2) # ERROR
```

We can apply difference operations on multiple sets using both techniques. For example,

```a = {10, 20, 30, 40}
b = {20, 30, 40, 50}
c = {30, 40, 50, 60}
d = {40, 50, 60, 70}

print("Method", a.difference(b, c, d)) #Method

print("Operator", a - b - c - d)  #Operator

#Output
Method {10}
Operator {10}
```

### Checking Disjoint Operation

isdisjoint() method can be used to find if the two given sets (let s1 and s2) are disjoint or not. The two sets are said to be disjoint if they do not contain any common elements. There is no corresponding operator for this method. For example,

```a = {10, 20, 30, 40}
b = {20, 30, 40, 50}
c = {70, 80, 90, 100}

print(a.isdisjoint(b))
print(a.isdisjoint(c))

#Output
False
True
```

### Checking Subset Operation

issubset() method can be applied to check if a set is the subset of another set or not. We can determine the same using the ( <= ) operator.

```a = {10, 20, 30, 40, 50, 60 , 70}
b = {100, 110, 40}
c = {30, 40, 60}

print("METHOD")
print(b.issubset(a))
print(c.issubset(a))

print("OPERATOR")
print(b <= a)
print(c <= a)

#Output
METHOD
False
True
OPERATOR
False
True

```

A set is always subset to itself. it means s1 <= s1, always returns True.

We can use s1 <  s2 to check if the set s1 is a proper subset of s2. It means s1 < s1 returns a False. The operator ( < ) is the only way to check the proper subset. There is no corresponding method for this operator.

### Checking Superset Operation

issuperset() method can be applied to check if a set is the superset of another set or not. A set s1 is considered a superset of set s2 if all the elements of s1 are contained by the s2. We can determine the same using the ( > = ) operator.

```a = {10, 20, 30, 40, 50, 60 , 70}
b = {100, 110, 40}
c = {30, 40, 60}

print("METHOD")
print(a.issuperset(b))
print(a.issuperset(c))

print("OPERATOR")
print(a >= b)
print(a > c)

#Output
METHOD
False
True
OPERATOR
False
True
```

### Updating Sets

The elements in the sets are immutable types, still, we can update the contents of a set. There are various operations to modify the contents of a set.

The easiest way to update a set is the update() method, For example,

```a = {10, 20, True, 'Some text'}

a.update((15,25))

print(a)

#Output
{True, 10, 15, 20, 'Some text', 25}
```

For example, each of the union, intersection, difference, and symmetric difference operators can be augmented with an assignment operator to modify a set. For example,

For example,

```a = {10, 20, True, 'Some text'}
b = {12.3, 19.5, 10}
a |= b

print(a)

a = {10, 20, True, 'Some text'}
b = {12.3, 19.5, 10}

a &= b
print(a)

#Output
{True, 19.5, 20, 'Some text', 10, 12.3}
{10}
```

We can use intersection_update() and intersection_difference() method corresponding to the ( |= ) and ( &=) operators.

We can also use the add(<element>), remove(<element>) and discard(<element>) methods to update a set by add, remove and remove operations from a set. The difference between the remove() and discard() method is that the first one raises an exception if the element is not found in the set.

```a = {10, 20, True, 'Some text', 17.5}
print(a)
a.remove(10)
print(a)
print(a)

#Output
{True, 'Some text', 10, 17.5, 20, 'new item'}
{True, 'Some text', 17.5, 20, 'new item'}
{True, 'Some text', 17.5, 20, 'new item'}
```

The pop() method remove an item arbitrarily from the set.
The clear() method clears the set.

```a = {10, 20, True, 'Some text', 17.5}

a.pop()
print(a)
a.clear()
print('Cleared the Set')
print(a)

#Output
{'Some text', 10, 17.5, 20}
Cleared the Set
set()

```