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.

Benefits of tuple against List are: - Faster than list - Protects your data against accidental change - Can be used as key in dictionaries, list can’t

3.1.1 Creating

3.1.1.1 Constructor

# mylist = [1,2,3]
# print(tuple(mylist))

3.1.1.2 Assignment

With or Without ()

This is a formal syntax for defining tuple, items inside ( ) notation. Assignment although works without (), it is not recommended.

t1 = (1,2,3,'o','apple')
t2 = 1,2,3,'o','apple'

print(type(t1), type(t2))
#:> <class 'tuple'> <class 'tuple'>

3.1.2 Accessing

print( t[1], t[1:3] )

3.1.3 Duplicating

Use normal assignment = to duplicate. Reference of the memory address is copied. Data is actually not duplicated in memory.

original = (1,2,3,4,5)
copy_test = original
print(original)
#:> (1, 2, 3, 4, 5)
print(copy_test)
#:> (1, 2, 3, 4, 5)

The copy and original has the same memory location.

print('Original ID: ', id(original))
#:> Original ID:  139903753534832
print('Copy ID:     ', id(copy_test))
#:> Copy ID:      139903753534832

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 Creating List

3.2.1.1 Empty List

empty = []      # literal assignment method
empty = list()  # constructor method
print (empty)
#:> []

3.2.1.2 Literal Assignment

  • Multiple data types is allowed in a list
[123,'abc',456, None]
#:> [123, 'abc', 456, None]

Constructor

  • Note that list(string) will split the string into letters
list('hello')
#:> ['h', 'e', 'l', 'l', 'o']

3.2.2 Accessing Items

Access specific index number

food = ['bread', 'noodle', 'rice', 'biscuit','jelly','cake']
print (food[2])  # 3rd item
#:> rice
print (food[-1]) # last item
#:> cake

Access range of indexes

print (food[:4])     # first 3 items
#:> ['bread', 'noodle', 'rice', 'biscuit']
print (food[-3:])    # last 3 items
#:> ['biscuit', 'jelly', 'cake']
print (food[1:5])    # item 1 to 4
#:> ['noodle', 'rice', 'biscuit', 'jelly']
print (food[5:2:-1]) # item 3 to 5, reverse order
#:> ['cake', 'jelly', 'biscuit']
print (food[::-1])   # reverse order
#:> ['cake', 'jelly', 'biscuit', 'rice', 'noodle', 'bread']

3.2.3 Methods

3.2.3.1 Remove Item(s)

Removal of non-existance item will result in error

Search and remove first matching item

food = list(['bread', 'noodle', 'rice', 'biscuit','jelly','cake','noodle'])
food.remove('noodle')
print (food)
#:> ['bread', 'rice', 'biscuit', 'jelly', 'cake', 'noodle']

Remove last item

food.pop()
#:> 'noodle'
print (food)
#:> ['bread', 'rice', 'biscuit', 'jelly', 'cake']

Remove item at specific position

food.pop(1)  # counter start from 0
#:> 'rice'
print(food)
#:> ['bread', 'biscuit', 'jelly', 'cake']
food.remove('jelly')
print(food)
#:> ['bread', 'biscuit', 'cake']

3.2.3.2 Appending Item (s)

Append One Item

food.append('jelly')
print (food)
#:> ['bread', 'biscuit', 'cake', 'jelly']

Append Multiple Items extend() will expand the list/tupple argument and append as multiple items

food.extend(['nand','puff'])
print (food)
#:> ['bread', 'biscuit', 'cake', 'jelly', 'nand', 'puff']

3.2.3.3 Other Methods

Reversing the order of the items

food.reverse()
food
#:> ['puff', 'nand', 'jelly', 'cake', 'biscuit', 'bread']

Locating the Index Number of An Item

food.index('biscuit')
#:> 4

Count occurance

test = ['a','a','a','b','c']
test.count('a')
#:> 3

Sorting The Order of Items

food.sort()
print (food)
#:> ['biscuit', 'bread', 'cake', 'jelly', 'nand', 'puff']

3.2.4 Operator

3.2.4.1 Concatenation

Concatenating Lists

Two lists can be concatenanted using ‘+’ operator.

['dog','cat','horse'] + ['elephant','tiger'] + ['sheep']
#:> ['dog', 'cat', 'horse', 'elephant', 'tiger', 'sheep']

3.2.5 List is Mutable

The reference of list variable won’t change after adding/removing its item

food = ['cake','jelly','roti','noodle']
print ('food : ',id(food))
#:> food :  139903753597728
food += ['salad','chicken']
print ('food : ',id(food))
#:> food :  139903753597728

A function is actually an object, which reference never change, hence mutable

def spam (elem, some_list=['a','b']):
    some_list.append(elem)
    return some_list

print (spam(1,['x']))
#:> ['x', 1]
print (spam(2)) ## second parameter is not passed
#:> ['a', 'b', 2]
print (spam(3)) ##  notice the default was remembered
#:> ['a', 'b', 2, 3]

3.2.6 Duplicate or Reference

Use = : It just copy the refernce. IDs are similar

original = [1,2,3,4,5]
copy_test = original
print('Original ID: ', id(original))
#:> Original ID:  139903753598368
print('Copy ID:     ', id(copy_test))                          
#:> Copy ID:      139903753598368
original[0]=999   ## change original
print(original)
#:> [999, 2, 3, 4, 5]
print(copy_test)  ## copy affected
#:> [999, 2, 3, 4, 5]

Duplicate A List Object with copy(). Resulting IDs are different

original = [1,2,3,4,5]
copy_test = original.copy()
print(original)
#:> [1, 2, 3, 4, 5]
print(copy_test)
#:> [1, 2, 3, 4, 5]
print('Original ID: ', id(original))
#:> Original ID:  139903753608240
print('Copy ID:     ', id(copy_test))
#:> Copy ID:      139903914202208
original[0] = 999  ## change original
print(original)    
#:> [999, 2, 3, 4, 5]
print(copy_test)   ## copy not affected
#:> [1, 2, 3, 4, 5]

Passing To Function As Reference

def func(x):
    print (x)
    print('ID in Function:      ', id(x))
    x.append(6)    ## modify the refrence
    
my_list = [1,2,3,4,5]
print('ID outside Function: ', id(my_list))
#:> ID outside Function:  139903914209360
func(my_list)  ## call the function, pass the reference
#:> [1, 2, 3, 4, 5]
#:> ID in Function:       139903914209360
print(my_list) ## content was altered
#:> [1, 2, 3, 4, 5, 6]

3.2.7 List Is Iterable

3.2.7.1 For Loop

s = ['abc','abcd','bcde','bcdee','cdefg']
for x in s:
    if 'abc' in x:
        print (x)
#:> abc
#:> abcd

3.2.7.2 List Comprehension

This code below is a shorform method of for loop and if.

old_list = ['abc','abcd','bcde','bcdee','cdefg']
[x for x in old_list if 'abc' in x]
#:> ['abc', 'abcd']

Compare to traditional version of code below:

new_list = []
old_list = ['abc','abcd','bcde','bcdee','cdefg']
for x in old_list:
    if 'abc' in x:
        new_list.append(x)
        
print( new_list )
#:> ['abc', 'abcd']

3.2.8 Conversion

Convert mutable list to immutable tuple with tuple()

original = [1,2,3]
original_tuple = tuple(original)
print( id(original),
       id(original_tuple))
#:> 139903753700928 139903753630976

3.2.9 Built-In Functions Applicable To List

Number of Elements

len(food)
#:> 6

Max Value

test = [1,2,3,5,5,3,2,1]
m = max(test)
test.index(m)  ## only first occurance is found
#:> 3

3.3 Dictionaries

Dictionary is a list of index-value items.

3.3.1 Creating dict

3.3.1.1 From Literals

Simple Dictionary

animal_counts = { 'cats' : 2, 'dogs' : 5, 'horses':4}
print (animal_counts)
#:> {'cats': 2, 'dogs': 5, 'horses': 4}
print( type(animal_counts) )
#:> <class 'dict'>

Dictionary with list

animal_names = {'cats':   ['Walter','Ra'],
                'dogs':   ['Jim','Roy','John','Lucky','Row'],
                'horses': ['Sax','Jack','Ann','Jeep']
               }
animal_names
#:> {'cats': ['Walter', 'Ra'], 'dogs': ['Jim', 'Roy', 'John', 'Lucky', 'Row'], 'horses': ['Sax', 'Jack', 'Ann', 'Jeep']}

3.3.1.2 From Variables

cat_names = ['Walter','Ra','Jim']
dog_names = ['Jim','Roy','John','Lucky','Row']
horse_names= ['Sax','Jack','Ann','Jeep']
animal_names = {'cats': cat_names, 'dogs': dog_names, 'horses': horse_names}
animal_names
#:> {'cats': ['Walter', 'Ra', 'Jim'], 'dogs': ['Jim', 'Roy', 'John', 'Lucky', 'Row'], 'horses': ['Sax', 'Jack', 'Ann', 'Jeep']}

3.3.2 Accessing dict

3.3.2.1 Get All Keys

print (animal_names.keys())
#:> dict_keys(['cats', 'dogs', 'horses'])
print (sorted(animal_names.keys()))
#:> ['cats', 'dogs', 'horses']

3.3.2.2 Get All Values

print (animal_names.values())
#:> dict_values([['Walter', 'Ra', 'Jim'], ['Jim', 'Roy', 'John', 'Lucky', 'Row'], ['Sax', 'Jack', 'Ann', 'Jeep']])
print (sorted(animal_names.values()))
#:> [['Jim', 'Roy', 'John', 'Lucky', 'Row'], ['Sax', 'Jack', 'Ann', 'Jeep'], ['Walter', 'Ra', 'Jim']]

3.3.2.3 Access value with Specific Key

Use [ key ] notation. However, this will return Error if key does not exist

animal_names['dogs']
#:> ['Jim', 'Roy', 'John', 'Lucky', 'Row']

Use get( key ) notation. will return None if key does not exist

print (animal_counts.get('cow'))
#:> None

3.3.3 Dict Is Mutable

3.3.3.1 Update/Append

Use [key] notation to update o append the content of element.

animal_names['dogs'] = ['Ali','Abu','Bakar']
animal_names
#:> {'cats': ['Walter', 'Ra', 'Jim'], 'dogs': ['Ali', 'Abu', 'Bakar'], 'horses': ['Sax', 'Jack', 'Ann', 'Jeep']}

Use clear() to erase all elements

animal_names.clear()

3.3.4 Iterating Elements

Loop through .items()

animal_dict = { 'cats' : 2, 'dogs' : 5, 'horses':4}

for key,val in animal_dict.items():
  print( key, val )
#:> cats 2
#:> dogs 5
#:> horses 4

3.4 Sets

Set is unordered collection of unique items. Set is mutable

3.4.1 Creation

Set can be declared with {}, unlike list creation uses ‘[].’

myset = {'a','b','c','d','a','b','e','f','g'}
print (myset) # notice no repetition values
#:> {'c', 'e', 'b', 'f', 'g', 'd', 'a'}

Set can be created from list, and then converted back to list

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      :  {'c', 'e', 'b', 'f', 'g', 'd', 'a'} 
#:> Convert back to list:  ['c', 'e', 'b', 'f', 'g', 'd', 'a']

3.4.2 Membership Test

print ('a' in myset)      # is member ?
#:> True
print ('f' not in myset)  # is not member ?
#:> False

3.4.3 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)
#:> Is Subset :  True
print ('Is Proper Subet : ', mysubset < myset)
#:> Is Proper Subet :  False

3.4.4 Union using |

{'a','b','c'} | {'a','e','f'}
#:> {'c', 'e', 'b', 'f', 'a'}

3.4.5 Intersection using &

Any elments that exist in both left and right set

{'a','b','c','d'} & {'c','d','e','f'}
#:> {'d', 'c'}

3.4.6 Difference using -

Remove right from left

{'a','b','c','d'} - {'c','d','e','f'}
#:> {'b', 'a'}

3.5 range

range(X) generates sequence of integer object

range (lower_bound, upper_bound, step_size)  
# lower bound is optional, default = 0
# upper bound is not included in result
# step is optional, default = 1

Use list() to convert in order to view actual sequence of data

r = range(10)     # default lower bound =0, step =1
print (type (r))
#:> <class 'range'>
print (r)
#:> range(0, 10)
print (list(r))
#:> [0, 1, 2, 3, 4, 5, 6, 7, 8, 9]

More Examples

print (list(range(2,8)))    # step not specified, default 1
#:> [2, 3, 4, 5, 6, 7]
print ('Odds Number : ' , list(range(1,10,2))) # generate odds number
#:> Odds Number :  [1, 3, 5, 7, 9]