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.2.6 Tuple Conversion

my_list  = [1,2,3]
my_tuple = tuple(my_list)   ## concert to tuple using constructor

my_list
my_tuple
## [1, 2, 3]
## (1, 2, 3)

3.2.7 Built-In Functions

my_numbers = [1,2,3,5,5,3,2,1]

len(my_numbers)    ## numner of elements
max(my_numbers)    ## maximum value of elements
sorted(my_numbers) ## sort ascending
sorted(my_numbers, reverse=True) ## sort descending
## 8
## 5
## [1, 1, 2, 2, 3, 3, 5, 5]
## [5, 5, 3, 3, 2, 2, 1, 1]

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'}