Tuples


######## CHAPTER 10
######## TUPLES
######## 5:23:06

# ============================================
# ============================================
# ============================================
# ============================================

# Tuples are like lists, having elements which are indexed starting at 0.

# Differences:
    # There are no square brackets. instead () are used.
    # Tuples are immutable - similar to string.
        # Reason: Efficiency.
    # Functions not allowed with Tuples.
        # sorting  --  .sort()
        # appending --  .append()
        # reversing  --  .reverse()

# Allowed with Tuple
    # 'count'
    # 'index'

# whereas allowed with list
    # append
    # count
    # extend
    # index
    # insert
    # pop
    # remove
    # reverse
    # sort

# why they are so efficient:
    # Python does not have to build tuple structures to be modifieable, they are simpler and more efficient in terms of "memory use" and "performance" than lists.
# When we prefer to use tuples:
    # When we are making "temporary variables" and then temporarily use it for just little bit and then throw it away, then we prefer tuples over lists.

# --------

# Tuples and Assignments
    # Tuples (like other variable creations) can be used on left hand side of an assignment statement.
    # we can even omit the parentheses.

# in other words, you can put tuple that includes variables on the left hand side of the assignment.        ### a Really Cool Feature which is not done by anyother language so far.

(x, y) = (4, 'fred')
print(y)                # fred
print(x)                # 4

# again, By the way, we can even omit the parentheses.

a, b = 99 , 98
print(a)                # 99

### BUT: if you don't match the number on both side then you get into trouble.

# if you say -- x = tuple, thats an other story, that is a tuple.


# You can even do things like : return the tuple from function, that's a real nice python feature. ?????

# -------------------
# -------------------
# -------------------
# -------------------

### Tuple and  Dictionaries ###
### Tuple and  Dictionaries ###
### Tuple and  Dictionaries ###


# the item() method in dictionaries returns a list of (key, value) tuples.

d = dict()
d['csev'] = 2
d['cwen'] = 4

# confirmation of dictionary:
print(d)            # {'csev': 2, 'cwen': 4}

# getting tuples from dictionary:
tups = d.items()
print(tups)         # dict_items([('csev', 2), ('cwen', 4)])        # this is a list of tuples

# getting pairs of key-value from dictionary:
for (k, v) in d.items():
    print(k, v)
                    # csev 2
                    # cwen 4

# ---------------------------
# ---------------------------
# ---------------------------
# ---------------------------

### Tuples are Comparable ###

# it does scan until it has the definitive answer.
# tuples are comparable just like strings
    # But, Lists are also behaving same like tuples.

print((0, 1, 2) < (5, 1, 2))                    # True --   Tuple               # since 5 is greater than 1, so no need to check further
print((0, 1, 2000000) < (0, 3, 4))              # True --   //                  # since 3 is greater than 1, so no need to check further
print(('Jones', 'Sally') < ('Jones', 'Sam'))    # True --   //                  # since l is greater than m, so no need to check further
print(('Jones', 'Sally') > ('Adams', 'Sam'))    # True --   //                  # since J is greater than A, so no need to check further
print(['Jones', 'Sally'] > ['Adams', 'Sam'])    # True --   List Comparison

# when it finds the definitive answer, it doesn't scan any further.

# ---------------------------
# ---------------------------
# ---------------------------
# ---------------------------

###### sorting Lists of Tuples.
    # please note, not tuples, but the lists of tuples. since the tuple allow only two functions i.e. count() and index().
# objective: to get a sorted version of a dictionary

# first we sort the dictionary by using "items() method" and "sorted() function".

d = {'a': 10, 'b': 1, 'c': 22}
print(d.items())                        # dict_items([('a', 10), ('b', 1), ('c', 22)])      # tuples are made
print(sorted(d.items()))                # [('a', 10), ('b', 1), ('c', 22)]                  # sorted

e = {'z': 10, 'b': 1, 'c': 22}
print(e.items())                        # dict_items([('z', 10), ('b', 1), ('c', 22)])      # tuples are made
print(sorted(e.items()))                # [('b', 1), ('c', 22), ('z', 10)]                  # sorted

# ---------------------------
# ---------------------------

### Using Sorted

# using directly "sorted()" function, that takes a sequence as a parameter and returns a sorted sequence.

d = {'a': 10, 'k': 1, 'c': 22}
t = sorted(d.items())
print(t)                                # [('a', 10), ('c', 22), ('k', 1)]

# ---------------------------
# ---------------------------
            #### OR -- direct use in loop

d = {'a': 10, 'k': 1, 'c': 22}
for k, v in sorted(d.items()):                  # this is still a tuple without the parentheses
    print(k, v)
                                            # a 10
                                            # c 22
                                            # k 1

                                                # in above example, output is sorted by "key".

# ---------------------------
# ---------------------------

#### now sort by values ####
#### now sort by values ####
#### now sort by values ####
#### now sort by values ####

    # for this purpose, we have to construct a list of tuples of the form (value, key), then we can sort by value.
        # we do this by a "for-loop" that creates a list of tuples.

c = {'a': 10, 'b': 1, 'c':22}
temp = list()
for k, v in c.items():
    temp.append((v, k))
print(temp)                     # [(10, 'a'), (1, 'b'), (22, 'c')]


# for descending order
temp_descending = sorted(temp, reverse=True)
print(temp_descending)                 # [(22, 'c'), (10, 'a'), (1, 'b')]

# for ascending order
temp_ascending = sorted(temp, reverse=False)
print(temp_ascending)                # [(1, 'b'), (10, 'a'), (22, 'c')]

# Or
temp_ascending2 = sorted(temp)
print(temp_ascending2)                 # [(1, 'b'), (10, 'a'), (22, 'c')]

# ---------------------------
# ---------------------------
# ---------------------------
# ---------------------------

# Finding top 10 most common words
# Finding top 10 most common words
# Finding top 10 most common words
# Finding top 10 most common words
# Finding top 10 most common words

    # 1: open file
    # 2: create new empty dictionary
    # 3: through for loop in opened file (handle), split all lines to get words
    # 4: through for loop (nested) in each splitted line, count the words using "get-method". Note: count variable (dictionary) is already created outside loops.
    # 5: create an empty list for making list of tuples through for loop
    # 6: use two iteration variable (tuples), and apply it on dictionary created in first block of loops.
    # 7: take care of order or tuples; place values first and then the keys.
    # 8: apply "sorted()", and "reverse = True" to get descending order tuples.
    # 9: Now for top 10 most commonly used words, just use printing of list item through using index numbers


# Opening a file
fhand = open('intro.txt')

# creating dictionary.
count = dict()
for line in fhand:
    words = line.split()
    for word in words:
        count[word] = count.get(word, 0) + 1
# print(count)      # just to confirm if code is working so far!

# creating lists of tuples where values comes first and then the keys (values and keys of dictionary created earlier)
lst = list()
for k, v in count.items():
    # lst.append(v, k)      # since append takes only one arguments so this code will give T.B.
    newtup = (v, k)
    lst.append(newtup)
# print(lst)                # again to confirm if code is working so far.

# sorting the tuples in descending order
lst = sorted(lst, reverse= True)            # instead of creating new name, same name (i.e. "lst") is used for sorted list.
# print(lst)                # again to confirm if code is working so far.

# REQUIREMENT:: to get key and value in order, we have to organise the order again.

for v, k in lst[:10]:
    print(k, v)
                               # the 226
                               # to 204
                               # a 165
                               # and 160
                               # you 130
                               # is 112
                               # of 103
                               # Python 85
                               # that 68
                               # in 66



# the requirement: without "key-value" order
print(lst[:10])                     # [(226, 'the'), (204, 'to'), (165, 'a'), (160, 'and'), (130, 'you'), (112, 'is'), (103, 'of'), (85, 'Python'), (68, 'that'), (66, 'in')]

# Further practice: in case you want output in every next line.
for e in lst[:10]:
    print(e)                        # (226, 'the')
                                    # (204, 'to')
                                    # (165, 'a')
                                    # (160, 'and')
                                    # (130, 'you')
                                    # (112, 'is')
                                    # (103, 'of')
                                    # (85, 'Python')
                                    # (68, 'that')
                                    # (66, 'in')

# NOTICE: both dictionary and list were first created empty then through "for-loops" the content was put into them.

# alternative one liner code for sorting list (count-dictionary)


fhand = open('intro.txt')

count = dict()
for line in fhand:
    words = line.split()
    for word in words:
        count[word] = count.get(word, 0) + 1
print(count)
# alternative code for producing same result. "#//"
# Though that does not do counts, and
# does not give you top 10

# it just ensures listing and sorting the list
# lst = list()                            # //              --- code commented
# for k, v in count.items():              # //              --- code commented
#     newtup = (v, k)                     # //              --- code commented
#     lst.append(newtup)                  # //              --- code commented
# lst = sorted(lst, reverse= True)        # //              --- code commented

print(sorted([(v, k) for k, v in count.items()]))

# (v, k) for k, v in count.items()  -- this part is called list-comprehension.
# List Comprehension creates a "dynamic list".

### BUT ###
# I STILL HAVE TO FIGURE OUT HOW THIS CODE WILL PERFORM EQUAL PERFORMANCE AS COMPARE TO PREVIOUS ONE.
# MEANS: How the other code will be written for producing top 10 items,
# Since: the count list (dictionary) is already incorporated into this code to produce a sorted list (sorted-dictionary)
# remamber the "print(count)" has output in "{}".

# for v, k in lst[:10]:                 --- code commented
#   print(k, v)                         --- code commented


# ---------------------------
# ---------------------------

#### Alternatively for reverse order,,, just add reverse=True to sorted()

print(sorted([(v, k) for k, v in count.items()], reverse=True))


# ---------------------------
# ---------------------------

# one statement with list comprehension code.

c = {'a': 10, 'b': 1, 'c': 22}
print(sorted([(v, k) for k, v in c.items()]))                   # [(1, 'b'), (10, 'a'), (22, 'c')]
print(sorted([(v, k) for k, v in c.items()], reverse=True))     # [(22, 'c'), (10, 'a'), (1, 'b')]
# again if we use reverse=False notion (perhaps may be for some purpose in future:
print(sorted([(v, k) for k, v in c.items()], reverse=False))    # [(1, 'b'), (10, 'a'), (22, 'c')]

# ===========================================
# ===========================================
# ===========================================
# ===========================================

            #### CHAPTER 10 ####
            ####    Tuples  ####
            # Sorting a Dictionary using Tuples.

# Assignment: Creating lists of most common words.
# Assignment: how to sort a dictionary by the values instead of by the key.

fname = input('Enter File: ')
if len(fname) < 1:
    fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
    lin = lin.rstrip()
    wds = lin.split()
    for w in wds:
        di[w] = di.get(w, 0) + 1
print(di)                               # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

# Now we need pairs of (k, v) == tuples or items.

x = di.items()
print(x)                                # dict_items([('the', 7), ('clown', 2), ('ran', 2), ('after', 1), ('car', 3), ('and', 3), ('into', 1), ('tent', 2), ('fell', 1), ('down', 1), ('on', 1)])

# it just take to put "sorted()" in code
# here sorting is done alfabetically only.
y = sorted(di.items())
print(y)
                                        # [('after', 1), ('and', 3), ('car', 3), ('clown', 2), ('down', 1), ('fell', 1), ('into', 1), ('on', 1), ('ran', 2), ('tent', 2), ('the', 7)]
# it just take to put "reverse=True" inside sorted() to get Descending sorting.
z = sorted(di.items(), reverse=True)
print(z)
                                        # [('the', 7), ('tent', 2), ('ran', 2), ('on', 1), ('into', 1), ('fell', 1), ('down', 1), ('clown', 2), ('car', 3), ('and', 3), ('after', 1)]

# ----------------------------
# ----------------------------

## Clean code of above

fname = input('Enter File: ')
if len(fname) < 1:
    fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
    lin = lin.rstrip()
    wds = lin.split()
    for w in wds:
        di[w] = di.get(w, 0) + 1
print(di)                               # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}


x = di.items()
print(x)                                # dict_items([('the', 7), ('clown', 2), ('ran', 2), ('after', 1), ('car', 3), ('and', 3), ('into', 1), ('tent', 2), ('fell', 1), ('down', 1), ('on', 1)])

y = sorted(di.items())
print(y)
                                        # [('after', 1), ('and', 3), ('car', 3), ('clown', 2), ('down', 1), ('fell', 1), ('into', 1), ('on', 1), ('ran', 2), ('tent', 2), ('the', 7)]
z = sorted(di.items(), reverse=True)
print(z)
                                        # [('the', 7), ('tent', 2), ('ran', 2), ('on', 1), ('into', 1), ('fell', 1), ('down', 1), ('clown', 2), ('car', 3), ('and', 3), ('after', 1)]



# ---------------------------
# ---------------------------
### NOw code as per instructer ###

fname = input('Enter File: ')
if len(fname) < 1:
    fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
    lin = lin.rstrip()
    wds = lin.split()
    for w in wds:
        di[w] = di.get(w, 0) + 1
print(di)                               # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

x = sorted(di.items())
print(x[:5])                        # [('after', 1), ('and', 3), ('car', 3), ('clown', 2), ('down', 1)]
# --------------------
# --------------------
# --------------------

# Now we r abt to learn how to do sorting based on values in Tuples.
fname = input('Enter File: ')
if len(fname) < 1:
    fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
    lin = lin.rstrip()
    wds = lin.split()
    for w in wds:
        di[w] = di.get(w, 0) + 1
print(di)                               # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

# Requirement: List of tuples in form of (v, k).
# there are few ways to do this, following is one of those ways:
    # We have to hand construct the list.

# Create new empty list, having flipped the content of items of doctionary -- "di.items()".
    # Explaination: Here we are creating a list of tuples with "v, k" order from a dictionary already created from the file in previous section.
tmp = list()
for k, v in di.items():             # Since the dictionary is in form of (k, v) so we have to construct the loop using expression (k, v)
    # print(k, v)                   # printed just to check if the code is working good so far.
    newt = (v, k)                   # This can be called "making new tuples"
    tmp.append(newt)                # appending items (tuples) into new list (the list of tuples)

print('flipped: ', tmp)                 # flipped:  [(7, 'the'), (2, 'clown'), (2, 'ran'), (1, 'after'), (3, 'car'), (3, 'and'), (1, 'into'), (2, 'tent'), (1, 'fell'), (1, 'down'), (1, 'on')]
# Now we have list consisting of "v, k" tuples, and now we can sort that based on values i.e. "v". But there is also worth mentioning here:
    # Sorting is done by considering both items in the tuple.
        # i.e. when the first value is same in lets say two tuples, then it consider comparing 2nd item (i.e. key) by numaric or alphabetical order (just like string).
# indexing will be used to get the limited output as per our requirement. like "tmp[:5]"

### Only sorting
# tmp = sorted(tmp)
# print('sorted: ', tmp[:5])            # sorted:  [(1, 'after'), (1, 'down'), (1, 'fell'), (1, 'into'), (1, 'on')]

### Sorting with Descending Order.
    # since we want to get highest, so "reverse = True" will be used.
tmp = sorted(tmp, reverse=True)
print(tmp[:5])                          # [(7, 'the'), (3, 'car'), (3, 'and'), (2, 'tent'), (2, 'ran')]

# for the sake of printing out nicer, we can use "for-loop".
for v, k in tmp[:5]:
    print(k, v)
                        # the 7
                        # car 3
                        # and 3
                        # tent 2
                        # ran 2



# ---------------------------
# ---------------------------
# ---------------------------

### Clean Code ###
fname = input('Enter File: ')
if len(fname) < 1:
    fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
    lin = lin.rstrip()
    wds = lin.split()
    for w in wds:
        di[w] = di.get(w, 0) + 1
# print(di)                               # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

tmp = list()
for k, v in di.items():
    newt = (v, k)                   # This can be called "making new tuples"
    tmp.append(newt)                # appending items (tuples) into new list (the list of tuples)


tmp = sorted(tmp, reverse=True)
# print(tmp[:5])                          # [(7, 'the'), (3, 'car'), (3, 'and'), (2, 'tent'), (2, 'ran')]

for v, k in tmp[:5]:
    print(k, v)
                        # the 7
                        # car 3
                        # and 3
                        # tent 2
                        # ran 2



# ---------------------------
# why to use tuples when you can do the same with list?
    # tuples are more efficient.
    # we do not modify tuples within the list.
    # we do modify the list of tuples "temp", but the tuples within the list, we are not gonna modify.




######## CHAPTER 10
######## TUPLES
######## 5:23:06

# ============================================
# ============================================
# ============================================
# ============================================

# Tuples are like lists, having elements which are indexed starting at 0.

# Differences:
# There are no square brackets. instead () are used.
# Tuples are immutable - similar to string.
# Reason: Efficiency.
# Functions not allowed with Tuples.
# sorting -- .sort()
# appending -- .append()
# reversing -- .reverse()

# Allowed with Tuple
# 'count'
# 'index'

# whereas allowed with list
# append
# count
# extend
# index
# insert
# pop
# remove
# reverse
# sort

# why they are so efficient:
# Python does not have to build tuple structures to be modifieable, they are simpler and more efficient in terms of "memory use" and "performance" than lists.
# When we prefer to use tuples:
# When we are making "temporary variables" and then temporarily use it for just little bit and then throw it away, then we prefer tuples over lists.

# --------

# Tuples and Assignments
# Tuples (like other variable creations) can be used on left hand side of an assignment statement.
# we can even omit the parentheses.

# in other words, you can put tuple that includes variables on the left hand side of the assignment. ### a Really Cool Feature which is not done by anyother language so far.

(x, y) = (4, 'fred')
print(y) # fred
print(x) # 4

# again, By the way, we can even omit the parentheses.

a, b = 99 , 98
print(a) # 99

### BUT: if you don't match the number on both side then you get into trouble.

# if you say -- x = tuple, thats an other story, that is a tuple.


# You can even do things like : return the tuple from function, that's a real nice python feature. ?????

# -------------------
# -------------------
# -------------------
# -------------------

### Tuple and Dictionaries ###
### Tuple and Dictionaries ###
### Tuple and Dictionaries ###


# the item() method in dictionaries returns a list of (key, value) tuples.

d = dict()
d['csev'] = 2
d['cwen'] = 4

# confirmation of dictionary:
print(d) # {'csev': 2, 'cwen': 4}

# getting tuples from dictionary:
tups = d.items()
print(tups) # dict_items([('csev', 2), ('cwen', 4)]) # this is a list of tuples

# getting pairs of key-value from dictionary:
for (k, v) in d.items():
print(k, v)
# csev 2
# cwen 4

# ---------------------------
# ---------------------------
# ---------------------------
# ---------------------------

### Tuples are Comparable ###

# it does scan until it has the definitive answer.
# tuples are comparable just like strings
# But, Lists are also behaving same like tuples.

print((0, 1, 2) < (5, 1, 2)) # True -- Tuple # since 5 is greater than 1, so no need to check further
print((0, 1, 2000000) < (0, 3, 4)) # True -- // # since 3 is greater than 1, so no need to check further
print(('Jones', 'Sally') < ('Jones', 'Sam')) # True -- // # since l is greater than m, so no need to check further
print(('Jones', 'Sally') > ('Adams', 'Sam')) # True -- // # since J is greater than A, so no need to check further
print(['Jones', 'Sally'] > ['Adams', 'Sam']) # True -- List Comparison

# when it finds the definitive answer, it doesn't scan any further.

# ---------------------------
# ---------------------------
# ---------------------------
# ---------------------------

###### sorting Lists of Tuples.
# please note, not tuples, but the lists of tuples. since the tuple allow only two functions i.e. count() and index().
# objective: to get a sorted version of a dictionary

# first we sort the dictionary by using "items() method" and "sorted() function".

d = {'a': 10, 'b': 1, 'c': 22}
print(d.items()) # dict_items([('a', 10), ('b', 1), ('c', 22)]) # tuples are made
print(sorted(d.items())) # [('a', 10), ('b', 1), ('c', 22)] # sorted

e = {'z': 10, 'b': 1, 'c': 22}
print(e.items()) # dict_items([('z', 10), ('b', 1), ('c', 22)]) # tuples are made
print(sorted(e.items())) # [('b', 1), ('c', 22), ('z', 10)] # sorted

# ---------------------------
# ---------------------------

### Using Sorted

# using directly "sorted()" function, that takes a sequence as a parameter and returns a sorted sequence.

d = {'a': 10, 'k': 1, 'c': 22}
t = sorted(d.items())
print(t) # [('a', 10), ('c', 22), ('k', 1)]

# ---------------------------
# ---------------------------
#### OR -- direct use in loop

d = {'a': 10, 'k': 1, 'c': 22}
for k, v in sorted(d.items()): # this is still a tuple without the parentheses
print(k, v)
# a 10
# c 22
# k 1

# in above example, output is sorted by "key".

# ---------------------------
# ---------------------------

#### now sort by values ####
#### now sort by values ####
#### now sort by values ####
#### now sort by values ####

# for this purpose, we have to construct a list of tuples of the form (value, key), then we can sort by value.
# we do this by a "for-loop" that creates a list of tuples.

c = {'a': 10, 'b': 1, 'c':22}
temp = list()
for k, v in c.items():
temp.append((v, k))
print(temp) # [(10, 'a'), (1, 'b'), (22, 'c')]


# for descending order
temp_descending = sorted(temp, reverse=True)
print(temp_descending) # [(22, 'c'), (10, 'a'), (1, 'b')]

# for ascending order
temp_ascending = sorted(temp, reverse=False)
print(temp_ascending) # [(1, 'b'), (10, 'a'), (22, 'c')]

# Or
temp_ascending2 = sorted(temp)
print(temp_ascending2) # [(1, 'b'), (10, 'a'), (22, 'c')]

# ---------------------------
# ---------------------------
# ---------------------------
# ---------------------------

# Finding top 10 most common words
# Finding top 10 most common words
# Finding top 10 most common words
# Finding top 10 most common words
# Finding top 10 most common words

# 1: open file
# 2: create new empty dictionary
# 3: through for loop in opened file (handle), split all lines to get words
# 4: through for loop (nested) in each splitted line, count the words using "get-method". Note: count variable (dictionary) is already created outside loops.
# 5: create an empty list for making list of tuples through for loop
# 6: use two iteration variable (tuples), and apply it on dictionary created in first block of loops.
# 7: take care of order or tuples; place values first and then the keys.
# 8: apply "sorted()", and "reverse = True" to get descending order tuples.
# 9: Now for top 10 most commonly used words, just use printing of list item through using index numbers


# Opening a file
fhand = open('intro.txt')

# creating dictionary.
count = dict()
for line in fhand:
words = line.split()
for word in words:
count[word] = count.get(word, 0) + 1
# print(count) # just to confirm if code is working so far!

# creating lists of tuples where values comes first and then the keys (values and keys of dictionary created earlier)
lst = list()
for k, v in count.items():
# lst.append(v, k) # since append takes only one arguments so this code will give T.B.
newtup = (v, k)
lst.append(newtup)
# print(lst) # again to confirm if code is working so far.

# sorting the tuples in descending order
lst = sorted(lst, reverse= True) # instead of creating new name, same name (i.e. "lst") is used for sorted list.
# print(lst) # again to confirm if code is working so far.

# REQUIREMENT:: to get key and value in order, we have to organise the order again.

for v, k in lst[:10]:
print(k, v)
# the 226
# to 204
# a 165
# and 160
# you 130
# is 112
# of 103
# Python 85
# that 68
# in 66



# the requirement: without "key-value" order
print(lst[:10]) # [(226, 'the'), (204, 'to'), (165, 'a'), (160, 'and'), (130, 'you'), (112, 'is'), (103, 'of'), (85, 'Python'), (68, 'that'), (66, 'in')]

# Further practice: in case you want output in every next line.
for e in lst[:10]:
print(e) # (226, 'the')
# (204, 'to')
# (165, 'a')
# (160, 'and')
# (130, 'you')
# (112, 'is')
# (103, 'of')
# (85, 'Python')
# (68, 'that')
# (66, 'in')

# NOTICE: both dictionary and list were first created empty then through "for-loops" the content was put into them.

# alternative one liner code for sorting list (count-dictionary)


fhand = open('intro.txt')

count = dict()
for line in fhand:
words = line.split()
for word in words:
count[word] = count.get(word, 0) + 1
print(count)
# alternative code for producing same result. "#//"
# Though that does not do counts, and
# does not give you top 10

# it just ensures listing and sorting the list
# lst = list() # // --- code commented
# for k, v in count.items(): # // --- code commented
# newtup = (v, k) # // --- code commented
# lst.append(newtup) # // --- code commented
# lst = sorted(lst, reverse= True) # // --- code commented

print(sorted([(v, k) for k, v in count.items()]))

# (v, k) for k, v in count.items() -- this part is called list-comprehension.
# List Comprehension creates a "dynamic list".

### BUT ###
# I STILL HAVE TO FIGURE OUT HOW THIS CODE WILL PERFORM EQUAL PERFORMANCE AS COMPARE TO PREVIOUS ONE.
# MEANS: How the other code will be written for producing top 10 items,
# Since: the count list (dictionary) is already incorporated into this code to produce a sorted list (sorted-dictionary)
# remamber the "print(count)" has output in "{}".

# for v, k in lst[:10]: --- code commented
# print(k, v) --- code commented


# ---------------------------
# ---------------------------

#### Alternatively for reverse order,,, just add reverse=True to sorted()

print(sorted([(v, k) for k, v in count.items()], reverse=True))


# ---------------------------
# ---------------------------

# one statement with list comprehension code.

c = {'a': 10, 'b': 1, 'c': 22}
print(sorted([(v, k) for k, v in c.items()])) # [(1, 'b'), (10, 'a'), (22, 'c')]
print(sorted([(v, k) for k, v in c.items()], reverse=True)) # [(22, 'c'), (10, 'a'), (1, 'b')]
# again if we use reverse=False notion (perhaps may be for some purpose in future:
print(sorted([(v, k) for k, v in c.items()], reverse=False)) # [(1, 'b'), (10, 'a'), (22, 'c')]

# ===========================================
# ===========================================
# ===========================================
# ===========================================

#### CHAPTER 10 ####
#### Tuples ####
# Sorting a Dictionary using Tuples.

# Assignment: Creating lists of most common words.
# Assignment: how to sort a dictionary by the values instead of by the key.

fname = input('Enter File: ')
if len(fname) < 1:
fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
lin = lin.rstrip()
wds = lin.split()
for w in wds:
di[w] = di.get(w, 0) + 1
print(di) # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

# Now we need pairs of (k, v) == tuples or items.

x = di.items()
print(x) # dict_items([('the', 7), ('clown', 2), ('ran', 2), ('after', 1), ('car', 3), ('and', 3), ('into', 1), ('tent', 2), ('fell', 1), ('down', 1), ('on', 1)])

# it just take to put "sorted()" in code
# here sorting is done alfabetically only.
y = sorted(di.items())
print(y)
# [('after', 1), ('and', 3), ('car', 3), ('clown', 2), ('down', 1), ('fell', 1), ('into', 1), ('on', 1), ('ran', 2), ('tent', 2), ('the', 7)]
# it just take to put "reverse=True" inside sorted() to get Descending sorting.
z = sorted(di.items(), reverse=True)
print(z)
# [('the', 7), ('tent', 2), ('ran', 2), ('on', 1), ('into', 1), ('fell', 1), ('down', 1), ('clown', 2), ('car', 3), ('and', 3), ('after', 1)]

# ----------------------------
# ----------------------------

## Clean code of above

fname = input('Enter File: ')
if len(fname) < 1:
fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
lin = lin.rstrip()
wds = lin.split()
for w in wds:
di[w] = di.get(w, 0) + 1
print(di) # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}


x = di.items()
print(x) # dict_items([('the', 7), ('clown', 2), ('ran', 2), ('after', 1), ('car', 3), ('and', 3), ('into', 1), ('tent', 2), ('fell', 1), ('down', 1), ('on', 1)])

y = sorted(di.items())
print(y)
# [('after', 1), ('and', 3), ('car', 3), ('clown', 2), ('down', 1), ('fell', 1), ('into', 1), ('on', 1), ('ran', 2), ('tent', 2), ('the', 7)]
z = sorted(di.items(), reverse=True)
print(z)
# [('the', 7), ('tent', 2), ('ran', 2), ('on', 1), ('into', 1), ('fell', 1), ('down', 1), ('clown', 2), ('car', 3), ('and', 3), ('after', 1)]



# ---------------------------
# ---------------------------
### NOw code as per instructer ###

fname = input('Enter File: ')
if len(fname) < 1:
fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
lin = lin.rstrip()
wds = lin.split()
for w in wds:
di[w] = di.get(w, 0) + 1
print(di) # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

x = sorted(di.items())
print(x[:5]) # [('after', 1), ('and', 3), ('car', 3), ('clown', 2), ('down', 1)]
# --------------------
# --------------------
# --------------------

# Now we r abt to learn how to do sorting based on values in Tuples.
fname = input('Enter File: ')
if len(fname) < 1:
fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
lin = lin.rstrip()
wds = lin.split()
for w in wds:
di[w] = di.get(w, 0) + 1
print(di) # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

# Requirement: List of tuples in form of (v, k).
# there are few ways to do this, following is one of those ways:
# We have to hand construct the list.

# Create new empty list, having flipped the content of items of doctionary -- "di.items()".
# Explaination: Here we are creating a list of tuples with "v, k" order from a dictionary already created from the file in previous section.
tmp = list()
for k, v in di.items(): # Since the dictionary is in form of (k, v) so we have to construct the loop using expression (k, v)
# print(k, v) # printed just to check if the code is working good so far.
newt = (v, k) # This can be called "making new tuples"
tmp.append(newt) # appending items (tuples) into new list (the list of tuples)

print('flipped: ', tmp) # flipped: [(7, 'the'), (2, 'clown'), (2, 'ran'), (1, 'after'), (3, 'car'), (3, 'and'), (1, 'into'), (2, 'tent'), (1, 'fell'), (1, 'down'), (1, 'on')]
# Now we have list consisting of "v, k" tuples, and now we can sort that based on values i.e. "v". But there is also worth mentioning here:
# Sorting is done by considering both items in the tuple.
# i.e. when the first value is same in lets say two tuples, then it consider comparing 2nd item (i.e. key) by numaric or alphabetical order (just like string).
# indexing will be used to get the limited output as per our requirement. like "tmp[:5]"

### Only sorting
# tmp = sorted(tmp)
# print('sorted: ', tmp[:5]) # sorted: [(1, 'after'), (1, 'down'), (1, 'fell'), (1, 'into'), (1, 'on')]

### Sorting with Descending Order.
# since we want to get highest, so "reverse = True" will be used.
tmp = sorted(tmp, reverse=True)
print(tmp[:5]) # [(7, 'the'), (3, 'car'), (3, 'and'), (2, 'tent'), (2, 'ran')]

# for the sake of printing out nicer, we can use "for-loop".
for v, k in tmp[:5]:
print(k, v)
# the 7
# car 3
# and 3
# tent 2
# ran 2



# ---------------------------
# ---------------------------
# ---------------------------

### Clean Code ###
fname = input('Enter File: ')
if len(fname) < 1:
fname = 'clown.txt'
hand = open(fname)

di = dict()
for lin in hand:
lin = lin.rstrip()
wds = lin.split()
for w in wds:
di[w] = di.get(w, 0) + 1
# print(di) # {'the': 7, 'clown': 2, 'ran': 2, 'after': 1, 'car': 3, 'and': 3, 'into': 1, 'tent': 2, 'fell': 1, 'down': 1, 'on': 1}

tmp = list()
for k, v in di.items():
newt = (v, k) # This can be called "making new tuples"
tmp.append(newt) # appending items (tuples) into new list (the list of tuples)


tmp = sorted(tmp, reverse=True)
# print(tmp[:5]) # [(7, 'the'), (3, 'car'), (3, 'and'), (2, 'tent'), (2, 'ran')]

for v, k in tmp[:5]:
print(k, v)
# the 7
# car 3
# and 3
# tent 2
# ran 2



# ---------------------------
# why to use tuples when you can do the same with list?
# tuples are more efficient.
# we do not modify tuples within the list.
# we do modify the list of tuples "temp", but the tuples within the list, we are not gonna modify.


Comments