Data Structures

  • List - mutable sequence, ordered and non-unique storage allowed;
  • Tuple - immutable sequence, ordered and non-unique storage allowed;
  • Set (consider later) - unordered and unindexed mutable collection with no duplicate elements;
  • Dictionary (consider later) - unordered and indexed mutable collection with no duplicate elements.

Lists

Creating

  • Using a pair of square brackets to denote the empty list: []
  • Using square brackets, separating items with commas: [a], [a, b, c]
  • Using a list comprehension: [x for x in iterable]
  • Using the type constructor: list() or list(iterable)

Note:

iterable i.e. elements of the object can be sequentially accessed

In [ ]:
empty_list = []
square_brackets_list = ["Hello",",","World","!", 2]
list_comprehension = [letter.upper() for letter in "some_string"]
with_type_constructor_list = list("some_string_2")
In [ ]:
print(empty_list,square_brackets_list,list_comprehension,with_type_constructor_list,sep="\n")
[]
['Hello', ',', 'World', '!', 2]
['S', 'O', 'M', 'E', '_', 'S', 'T', 'R', 'I', 'N', 'G']
['s', 'o', 'm', 'e', '_', 's', 't', 'r', 'i', 'n', 'g', '_', '2']

Accessing

In [ ]:
print(square_brackets_list[0])
print(square_brackets_list[1:3])
Hello
[',', 'World']

Changing

In [ ]:
list_hse = ['H', 'S', 'E']
#            0    1    2
list_hse[3] = '!'

str_hse = 'HSE'
list_hse[2] = 'Y'
# str_hse[2] = 'Y'
print(list_hse)
print(str_hse)
In [ ]:
square_brackets_list[10] = "Error Example" # remember about list range

Adding

In [ ]:
empty_list.append("new_item") # to the end of the sequence 
empty_list
Out[ ]:
['new_item', 'new_item', 'new_item']
In [ ]:
square_brackets_list.insert(1,"INSERTION_AT_1") # into list at the index
square_brackets_list.insert(10,"INSERTION_AT_10")
square_brackets_list
Out[ ]:
['Hello', 'INSERTION_AT_1', ',', 'World', '!', 2, 'INSERTION_AT_10']
In [ ]:
square_brackets_list[10] # list index out of range
---------------------------------------------------------------------------
IndexError                                Traceback (most recent call last)
<ipython-input-11-d72db95ab88b> in <module>()
----> 1 square_brackets_list[10] # list index out of range

IndexError: list index out of range

Removing / deleting

In [ ]:
square_brackets_list.remove("INSERTION_AT_10") # removing the specified item (tagret), if tagret not in list => ValueError
square_brackets_list
Out[ ]:
['Hello', 'INSERTION_AT_1', ',', 'World', '!']
In [ ]:
square_brackets_list.pop(1) #  removing the specified index, by default the specified index = the last item
square_brackets_list
Out[ ]:
['Hello', ',', 'World', '!']

The del statement is used to delete objects (variables, lists or its parts etc. -- everything is an object)

A useful application is to free memory

In [ ]:
a = 1
b_list = [1,2,3,4,'5']
In [ ]:
del a
a # name 'a' is not defined
---------------------------------------------------------------------------
NameError                                 Traceback (most recent call last)
<ipython-input-24-1686224acc3a> in <module>()
      1 del a
----> 2 a # name 'a' is not defined

NameError: name 'a' is not defined
In [ ]:
del b_list[0:2]
b_list
Out[ ]:
[3, 4, '5']
In [ ]:
del b_list

Clearing

In [ ]:
list_of_letters = [letter for letter in "qwertyuiopasdfghjklzxcvbnm"]
print("LIST WITH LETTERS:",list_of_letters,sep='\n')
list_of_letters.clear()
print("EMPTY LIST:",list_of_letters,sep='\n')
LIST WITH LETTERS:
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm']
EMPTY LIST:
[]

Other list methods

In [ ]:
list_of_letters = [letter for letter in "qwertyuiopasdfghjklzxcvbnm"]
print(list_of_letters)

list_of_letters.reverse()
answer = reversed(list_of_letters)
print(list_of_letters) # reversing list

answer = sorted(list_of_letters)
list_of_letters.sort(reverse=True) # sorting. Remember! sort() method accepts two argument and returns None 
print(list_of_letters)

m_ind = list_of_letters.index('m') # find the first item whose value is equal to target
print(list_of_letters[m_ind])

list_of_letters.extend(list('1234567890')) # iterable extending
print(list_of_letters)

print("LIST SIZE:",len(list_of_letters)) # list length
['q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm']
['m', 'n', 'b', 'v', 'c', 'x', 'z', 'l', 'k', 'j', 'h', 'g', 'f', 'd', 's', 'a', 'p', 'o', 'i', 'u', 'y', 't', 'r', 'e', 'w', 'q']
['z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a']
m
['z', 'y', 'x', 'w', 'v', 'u', 't', 's', 'r', 'q', 'p', 'o', 'n', 'm', 'l', 'k', 'j', 'i', 'h', 'g', 'f', 'e', 'd', 'c', 'b', 'a', '1', '2', '3', '4', '5', '6', '7', '8', '9', '0']
LIST SIZE: 36
In [ ]:
a = 1
b = 0
a, b = b, a
example_tuple = (b, a)
a, b = example_tuple

print(a, b)
0 1

Tuples

Creating

  • Using a pair of parentheses to denote the empty tuple: ()
  • Using a trailing comma for a singleton tuple: a, or (a,)
  • Separating items with commas: a, b, c or (a, b, c)
  • Using the tuple() built-in: tuple() or tuple(iterable)
In [ ]:
empty_tuple = ()
singleton = 'singleton',
separated_tuple = ("Hello",",","World","!") # separated_tuple = "Hello",",","World","!"
with_type_constructor_tuple = tuple("some_string_2")
In [ ]:
# Important

tuple( ("Hello",",","World","!") ) # it works
tuple("Hello",",","World","!") # it doesn not work
In [ ]:
print(empty_tuple)
print(singleton)
print(separated_tuple)
print(with_type_constructor_tuple)
()
('singleton',)
('Hello', ',', 'World', '!')
('s', 'o', 'm', 'e', '_', 's', 't', 'r', 'i', 'n', 'g', '_', '2')
In [ ]:
a,b,c,d = separated_tuple # tuple unpacking
print(a,b,c,d)

a,b,c,d = d,c,a,b # tuple unpacking is not equal the following statement: a=d,b=c,c=a,d=b 
print(a,b,c,d) # not ! World ! World

hello,_,_,_ = separated_tuple # syntax allows "skipping" not necessary variables
print(hello)
Hello , World !
! World Hello ,
Hello

Accessing

In [ ]:
with_type_constructor_tuple[0]
Out[ ]:
's'

Changing/Adding/Removing

Tuples are immutable sequences

In [ ]:
with_type_constructor_tuple[0] = 'QQQQQQ' # 'tuple' object does not support item assignment
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-22-5214f9c36d3a> in <module>
----> 1 with_type_constructor_tuple[0] = 'QQQQQQ' # 'tuple' object does not support item assignment

TypeError: 'tuple' object does not support item assignment
In [ ]:
del with_type_constructor_tuple[0] # 'tuple' object doesn't support item deletion
---------------------------------------------------------------------------
TypeError                                 Traceback (most recent call last)
<ipython-input-23-7a8a7fd53430> in <module>
----> 1 del with_type_constructor_tuple[0] # 'tuple' object doesn't support item deletion

TypeError: 'tuple' object doesn't support item deletion
In [ ]:
del with_type_constructor_tuple # but you can delete a whole object

Methods

In [ ]:
letter_tuple = tuple("qwertyuiopasdfghjklzxcvbnm")
print(letter_tuple)

letter_index = letter_tuple.index('o')
print(letter_tuple[letter_index])

print("TUPLE SIZE:",len(letter_tuple)) # list length
('q', 'w', 'e', 'r', 't', 'y', 'u', 'i', 'o', 'p', 'a', 's', 'd', 'f', 'g', 'h', 'j', 'k', 'l', 'z', 'x', 'c', 'v', 'b', 'n', 'm')
o
TUPLE SIZE: 26

If-statements in sequences or if target item exists?

In [ ]:
if 'a' in ['1','2','a']:
    print("YES_list!")
if 'q' in ('q','w',0):
    print("YES_tuple!")
    
print(1 in ['1','2','3'])
YES_list!
YES_tuple!
False

For Loops Through Tuples, Lists and etc.

For Loops can be used for any iterable objects

In [ ]:
list_of_letters = list("qwertyuiopasdfghjklzxcvbnm")
In [ ]:
for i in range(len(list_of_letters)-1):
    print(list_of_letters[i]+list_of_letters[i+1], end='\t')
print()
for letter in list_of_letters:
    print(letter,end="\t")
print()
for number in tuple("1234567890"):
    print(number,end="\t")

print(number,letter)
qw	we	er	rt	ty	yu	ui	io	op	pa	as	sd	df	fg	gh	hj	jk	kl	lz	zx	xc	cv	vb	bn	nm	
q	w	e	r	t	y	u	i	o	p	a	s	d	f	g	h	j	k	l	z	x	c	v	b	n	m	
1	2	3	4	5	6	7	8	9	0	0 m
In [ ]:
for letter in list_of_letters:
    if letter in ['a','b','c']:
        print(letter,end="\t")
    else:
        print('*',end="\t")
*	*	*	*	*	*	*	*	*	*	a	*	*	*	*	*	*	*	*	*	*	c	*	b	*	*	
In [ ]:
for letter in list_of_letters:
    if letter in ['a','b','c']:
        continue
    print(letter,end="\t")
In [ ]:
for number in tuple((1,2,34,5,6,7,8,9,0)):
    if number%3==0:
        break
    print(number,end="\t")
In [ ]:
for letter in 'qwertyuiop':
    continue
else:
    print("Else keyword allows executing code inside when For Loop is finised")
In [ ]:
for letter in list_of_letters:
    if letter!='q':
        print(letter)
    for i in '1234567890':
        print(i,end="\t")

Enumerate Function

Enumerate allows to loop over iterable object and have an automatic counter.

In [ ]:
for j,letter in enumerate(list_of_letters[:6]): 
    print(j,letter)
0 q
1 w
2 e
3 r
4 t
5 y

Nested Loops

In [ ]:
for j,letter in enumerate(list_of_letters): 
    if letter in tuple('milk'):
        print("!"*90)
        continue
#     elif letter =='b':
#         break
    print(letter,j,sep='-itter_',end="\t")
    
    for i in '1234567890':
        print(i,end="\t")
    
    print()
q-itter_0	1	2	3	4	5	6	7	8	9	0	
w-itter_1	1	2	3	4	5	6	7	8	9	0	
e-itter_2	1	2	3	4	5	6	7	8	9	0	
r-itter_3	1	2	3	4	5	6	7	8	9	0	
t-itter_4	1	2	3	4	5	6	7	8	9	0	
y-itter_5	1	2	3	4	5	6	7	8	9	0	
u-itter_6	1	2	3	4	5	6	7	8	9	0	
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
o-itter_8	1	2	3	4	5	6	7	8	9	0	
p-itter_9	1	2	3	4	5	6	7	8	9	0	
a-itter_10	1	2	3	4	5	6	7	8	9	0	
s-itter_11	1	2	3	4	5	6	7	8	9	0	
d-itter_12	1	2	3	4	5	6	7	8	9	0	
f-itter_13	1	2	3	4	5	6	7	8	9	0	
g-itter_14	1	2	3	4	5	6	7	8	9	0	
h-itter_15	1	2	3	4	5	6	7	8	9	0	
j-itter_16	1	2	3	4	5	6	7	8	9	0	
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
z-itter_19	1	2	3	4	5	6	7	8	9	0	
x-itter_20	1	2	3	4	5	6	7	8	9	0	
c-itter_21	1	2	3	4	5	6	7	8	9	0	
v-itter_22	1	2	3	4	5	6	7	8	9	0	
b-itter_23	1	2	3	4	5	6	7	8	9	0	
n-itter_24	1	2	3	4	5	6	7	8	9	0	
!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

Range

One more mutable sequence type. The range() function allows to generate iterable integer objects and always used for loops with specified executing number of times.

range(stop) -> range object
range(start, stop[, step]) -> range object

In [ ]:
print(tuple(range(10)))
print(list(range(5,30,3)))
In [ ]:
for i in range(17,8,-1):
    print(i,end='\t')
    if i%9==0:
        print('\n',type(i),sep='')
In [ ]:
for i in range(10):
    for j in range(0,5):
        print(i,'*',j,'=',i*j,end='\t')
    print()
    
print()

for i in range(10):
    for j in range(5,10):
        print(i,'*',j,'=',i*j,end='\t')
    print()
In [ ]:
for i in range(len(list_of_letters)):
    print(i,list_of_letters[i],end='\t',sep='<-')
In [ ]:
list_of_letters_2 = list_of_letters.copy() # otherwise list_of_letters will be changed too
 
for i in range(len(list_of_letters_2)):
    list_of_letters_2[i] = '*'
    
print(list_of_letters_2,list_of_letters,sep='\n')

List Comprehensions (introduction)

In [ ]:
print([i for i in range(0,101,10)])
print()
print([i for i in range(20) if i%3]) # if i%3 equals if i%3==1
print()
print([i if i%2==0 else "*" for i in range(20)])
print()
print([(i,i**2,i**3) for i in range(10)])
print()
print([[j for j in range(i)] for i in range(10)]) # nested
[0, 10, 20, 30, 40, 50, 60, 70, 80, 90, 100]

[1, 2, 4, 5, 7, 8, 10, 11, 13, 14, 16, 17, 19]

[0, '*', 2, '*', 4, '*', 6, '*', 8, '*', 10, '*', 12, '*', 14, '*', 16, '*', 18, '*']

[(0, 0, 0), (1, 1, 1), (2, 4, 8), (3, 9, 27), (4, 16, 64), (5, 25, 125), (6, 36, 216), (7, 49, 343), (8, 64, 512), (9, 81, 729)]

[[], [0], [0, 1], [0, 1, 2], [0, 1, 2, 3], [0, 1, 2, 3, 4], [0, 1, 2, 3, 4, 5], [0, 1, 2, 3, 4, 5, 6], [0, 1, 2, 3, 4, 5, 6, 7], [0, 1, 2, 3, 4, 5, 6, 7, 8]]

Problem

Your program receives a list of numbers in a single line as an input.

Group every pair of consecutive inputs into a tuple, put these tuples in a list and print it.

If input contains an odd amount of numbers, the last tuple has to have only a single number in it.

Example input:

11 9 20 8 3 7 4 6 5 5 4 9 1

Example output:

[('11', '9'), ('20', '8'), ('3', '7'), ('4', '6'), ('5', '5'), ('4', '9'), ('1',)]
In [ ]:
input_data = input().split()

print(input_data)
11 9 20 8 3 7 4 6 5 5 4 9 1
['11', '9', '20', '8', '3', '7', '4', '6', '5', '5', '4', '9', '1']
In [ ]: