Chapter 3 Built-In Data Structure
3.1 Tuple
Tuple is an immutable list. Any attempt to change/update tuple will return error. It can contain different types of object just like list.
Benefits of tuple against List are:
- Tuple is Faster than list
- Tuple Protects your data against accidental change
- Can be used as key in dictionaries, list can’t
3.1.1 Creation
Tuple is created through assignment with or without brackets. To create tuple from list, use tuple() constructor.
t1 = (1,2,3,'o',(4,5,6)) ## with brackets
t2 = 1,2,3,'o','apple', (4,5,6) ## without brackets
t3 = tuple([1,2,3,'o','apple', (4,5,6)]) ## create from list using constructor
print(type(t1), type(t2), type(t3))## <class 'tuple'> <class 'tuple'> <class 'tuple'>
3.1.2 Accessor
Assessing single element returns the element. Assessing range of elements returns tuple.
print( t1[0], t1[1:3] )## 1 (2, 3)
3.1.3 Copy and Clone
Use normal assignment = to duplicate. Reference of the memory address is copied. Data is actually not duplicated in memory. To clone an tuple (different ID), convert to list then back to tuple again.
## Copy actually points to the same memory location
original = (1,2,3,4,5)
copy_test = original
clone_test = tuple(list(original)) ## convert to list then back to tuple
## The copy refers to the same content
print(original)## (1, 2, 3, 4, 5)
print(copy_test)## (1, 2, 3, 4, 5)
print(clone_test)
## Copy and original has the same memory location.## (1, 2, 3, 4, 5)
print('Original ID: ', id(original))## Original ID: 2145172309232
print('Copy ID: ', id(copy_test))## Copy ID: 2145172309232
print('Clone ID: ', id(clone_test)) ## clone has different ID## Clone ID: 2145172570256
3.2 List
- List is a collection of ordered items, where the items can be different data types
- You can pack list of items by placing them into []
- List is mutable
3.2.1 Creation
## Create Empty List
empty = [] # literal assignment method
empty = list() # constructor method
multiple = [123,'abc',456, None] ## multiple datatypes allowed
str_list = list('hello') ## [split into h,e,l,l,o]
multiple
str_list## [123, 'abc', 456, None]
## ['h', 'e', 'l', 'l', 'o']
3.2.2 Accessor
Use [] to specify single or range of objects to return. Index numner starts from 0.
food = ['bread', 'noodle', 'rice', 'biscuit','jelly','cake']
## Accessing Single Index, Returns Object
food[2] # 3rd item
food[-1] # last item
## Accessing Range Of Indexes, Return List
food[:4] # first 3 items
food[-3:] # last 3 items
food[1:5] # item 1 to 4
food[5:2:-1] # item 3 to 5, reverse order
food[::-1] # reverse order## 'rice'
## 'cake'
## ['bread', 'noodle', 'rice', 'biscuit']
## ['biscuit', 'jelly', 'cake']
## ['noodle', 'rice', 'biscuit', 'jelly']
## ['cake', 'jelly', 'biscuit']
## ['cake', 'jelly', 'biscuit', 'rice', 'noodle', 'bread']
3.2.3 Methods
All methods shown below is “inplace”, meaning the original data will be changed.
Remove Item(s)
Removal of non-existence item will result in error
food = list(['bread', 'noodle', 'rice', 'biscuit','jelly','biscuit','noodle'])
food.remove('biscuit') ## remove first found element
food.pop() ## remove last element, and return it
food.pop(1) ## remove second element, and return it
food## 'noodle'
## 'noodle'
## ['bread', 'rice', 'jelly', 'biscuit']
Appending
There are two methods to add elements to the tail. append() adds single element. extend() addes multiple elements.
food.append('durian') ## add single element to the tail
food.extend(['nand','puff']) ## add elements to the tail
food## ['bread', 'rice', 'jelly', 'biscuit', 'durian', 'nand', 'puff']
Other Methods
## ordering of elements
food.reverse() ## reverse current order
food.sort() ## sort ascending
food.sort(reverse=True) ## sort descending
food
## methods returning number
food.index('biscuit') ## return the index of first found element
food.count('biscuit') ## return occurance of element## ['rice', 'puff', 'nand', 'jelly', 'durian', 'bread', 'biscuit']
## 6
## 1
3.2.4 Operators
Concatenation
Two lists can be concatenated using ‘+’ operator.
animals = ['dog','cat','horse'] + ['elephant','tiger'] + ['sheep']List is Mutable
The reference of list variable won’t change after adding/removing its item
id(animals)
animals += ['chicken']
animals.pop()
id(animals) ## ID had not changed## 2145172581760
## 'chicken'
## 2145172581760
Copy and Clone
Assignment to another variable always refers to the same data.Use copy() method if you wish to clone the data, with different ID.
original = [1,2,3,4,5] ## original data
copy_test = original ## same ID as Original
clone_test = original.copy() ## different ID
print( id(original), id(copy_test), id(clone_test))## 2145172612096 2145172612096 2145172617408
Passing To Function As Reference
When passing list to functions, only the reference passed. Meaning all changes to the list within the function will be reflected outside the function.
my_list = [1,2,3,4,5]
def func(x):
print (x)
print('ID in Function: ', id(x))
x.append(6) ## modify the refrence
my_list
id(my_list)
func(my_list) ## passing reference to function
my_list ## content was altered
id(my_list)## [1, 2, 3, 4, 5]
## 2145172617472
## [1, 2, 3, 4, 5]
## ID in Function: 2145172617472
## [1, 2, 3, 4, 5, 6]
## 2145172617472
3.2.5 Iteration
For Loop
mylist = ['abc','abcd','bcde','bcdee','cdefg']
for x in mylist:
if 'abc' in x:
print (x)## abc
## abcd
List Comprehension
This code below is a short-form method of for loop and if. The output of list comprehension is a new list.
old_list = ['abc','abcd','bcde','bcdee','cdefg']
[x for x in old_list if 'abc' in x]## ['abc', 'abcd']
Code below is a long-version compared to list comprehension aboce.
new_list = []
old_list = ['abc','abcd','bcde','bcdee','cdefg']
for x in old_list:
if 'abc' in x:
new_list.append(x)
new_list## ['abc', 'abcd']
3.3 Dictionaries
Dictionary is a list of index-value items.
3.3.1 Creation
Simple Dictionary
empty_dict = {} ## create empty
animal_counts = { 'cats' : 2, 'dogs' : 5, 'horses':4}
type(animal_counts)
type(empty_dict)## <class 'dict'>
## <class 'dict'>
Dictionary with list
horse_names = ['Sax','Jack','Ann','Jeep']
animal_names = {'cats': ['Walter','Ra'],
'dogs': ['Jim','Roy','John','Lucky','Row'],
'horses': horse_names
}
animal_names## {'cats': ['Walter', 'Ra'], 'dogs': ['Jim', 'Roy', 'John', 'Lucky', 'Row'], 'horses': ['Sax', 'Jack', 'Ann', 'Jeep']}
3.3.2 Accessor
Get All Keys
animal_name_keys = animal_names.keys()
animal_name_keys ## it is a list
[x for x in animal_name_keys] ## it is iterable## dict_keys(['cats', 'dogs', 'horses'])
## ['cats', 'dogs', 'horses']
Get All Values
animal_name_values = animal_names.values()
animal_name_values ## it is a list
[x for x in animal_name_values] ## values are iterable## dict_values([['Walter', 'Ra'], ['Jim', 'Roy', 'John', 'Lucky', 'Row'], ['Sax', 'Jack', 'Ann', 'Jeep']])
## [['Walter', 'Ra'], ['Jim', 'Roy', 'John', 'Lucky', 'Row'], ['Sax', 'Jack', 'Ann', 'Jeep']]
Acceess With Key
Use [ key ] notation to get its value. However, this will return Error if key does not exist
animal_names['dogs']## ['Jim', 'Roy', 'John', 'Lucky', 'Row']
For a safer approach (not to return error when key doesn’t exist), use get( key ) notation. It will return None if key does not exist
animal_names.get('cow') ## does not exist, return None
animal_names.get('dogs')## ['Jim', 'Roy', 'John', 'Lucky', 'Row']
3.3.3 MACD
Update/Append
Use [key] notation to update or append the content of element. Use del to remove a key/value pair.
new_world = {} ## create empty
new_world['bacteria'] = ['Ameoba','Fractona'] ## add new key/value
new_world['alien'] = ['Ali','Abu'] ## add new key/value
new_world
new_world['bacteria'] = ['Mutu', 'Aru'] ## Update value
del new_world['alien'] ## delete key/value
new_world## {'bacteria': ['Ameoba', 'Fractona'], 'alien': ['Ali', 'Abu']}
## {'bacteria': ['Mutu', 'Aru']}
Use clear() to erase all elements
animal_names.clear()
animal_names ## now an empty dict## {}
3.3.4 Iteration
Example below shows how to iterate over keys (.keys()), values (.values()) and both key/values (.items()).
animal_dict = { 'cats' : 2, 'dogs' : 5, 'horses':4}
[ (key,val) for key,val in animal_dict.items()]
[x for x in animal_dict.values()] ## values are iterable
[x for x in animal_dict.keys()] ## keys are iterable## [('cats', 2), ('dogs', 5), ('horses', 4)]
## [2, 5, 4]
## ['cats', 'dogs', 'horses']
3.4 Sets
Set is unordered collection of unique items. Set is mutable
3.4.1 Creation
Set can be declared with {}, just like list creation uses ‘[]’.
myset = {'a','b','c','d','a','b','e','f','g'}
myset # notice no repetition values## {'a', 'b', 'g', 'f', 'c', 'd', 'e'}
Set can be created from list, and then converted back to list. This is the perfect way to make a list unique.
mylist = ['a','b','c','d','a','b','e','f','g']
myset = set(mylist)
my_unique_list = list(myset)
print (
'Original List : ', mylist,
'\nConvert to set : ', myset,
'\nConvert back to list: ', my_unique_list) # notice no repetition values## Original List : ['a', 'b', 'c', 'd', 'a', 'b', 'e', 'f', 'g']
## Convert to set : {'g', 'c', 'd', 'a', 'b', 'f', 'e'}
## Convert back to list: ['g', 'c', 'd', 'a', 'b', 'f', 'e']
3.4.2 Operators
Membership Test
'a' in myset # is member ?
'f' not in myset # is not member ?## True
## False
Subset Test
Subset Test : <=
Proper Subset Test : <
mysubset = {'d','g'}
mysubset <= myset## True
Proper Subset test that the master set contain at least one element which is not in the subset
mysubset = {'b','a','d','c','e','f','g'}
print ('Is Subset : ', mysubset <= myset)
print ('Is Proper Subet : ', mysubset < myset)## Is Subset : True
## Is Proper Subet : False
Union using |
{'a','b','c'} | {'a','e','f'}## {'a', 'b', 'f', 'c', 'e'}
Intersection using &
Any elments that exist in both left and right set
{'a','b','c','d'} & {'c','d','e','f'}## {'c', 'd'}
Difference using -
Remove right from left
{'a','b','c','d'} - {'c','d','e','f'}## {'a', 'b'}