#!/usr/bin/env python3
###################################################################################
# Python sorted() method - with custom sorts
#        sorted() can sort a list, a tuple, or a dictionary
#        sorted() returns a different list/dictionay
###################################################################################
print("Content-Type: text/html \n")     #http header with newline char (required for the web)
print('<pre>')                                      #enhance display for the web

#-- define sort functions ----------------------------------------------------

def by_lastname(element):                        #function to sort by lastname
    lastname = element[element.index(' ')+1:]    #find space, take all the way to end   
    return lastname

def by_lastname_firstname(element):              #function to sort by lastname
    firstname = element[:element.index(' ')]     #find space, take from start to space   
    lastname  = element[element.index(' ')+1:]   #find space, take all the way to end
    sort_keys = (lastname, firstname)            #sort keys is a tuple of (lastname, firstname)   
    return sort_keys

def by_2dim_lastname_firstname(element):         #function to sort 2 dimensional list
    firstname = element[0]                       #take element[0] which is firstname
    lastname  = element[1]                       #take element[1] which is lastname
    return (lastname, firstname)

def by_value(element):                           #function to sort dictionary by value
    (key, value) = element
    return value


print("\n--------------1 dimensional list ------------------------------------------------------------")

names  = ['Sam Sultan', 'George Washington', 'Michael Sultan', 'Abraham Lincoln', 'Donald Duck']
print("The original list.: ", names)
print()

names2 = sorted(names)                                        #sort ascending
print("Sorted ascending..: ", names2)
print()

names2 = sorted(names, reverse=True)                          #sort descending
print("Sorted descending.: ", names)
print()

names2 = sorted(names, key=by_lastname)                       #sort by lastname
print("Sorted by lastname: ", names2)  
print()

names2 = sorted(names, key=by_lastname_firstname)             #sort by lastname then firstname
print("Sorted by lastname then firstname: ", names2)  
print()


print("\n--------------2 dimensional list ------------------------------------------------------------")

dim2 = [['Sam','Sultan'],['George','Washington'],['Michael','Sultan'],['Abraham','Lincoln'],['Donald','Duck']] 
print("The original 2 dimensional list: ")
print("[", end="")
for row in dim2:
    print('\t', row)
print("]", '\n')

print("Sorted ascending..: ")
dim2s = sorted(dim2)                                      #sort 2 dim ascending
for row in dim2s:
    print('\t', row)
print("]", '\n')

print("Sorted descending.: ")
dim2s = sorted(dim2, reverse=True)                        #sort 2 dim descending
print("[", end="")
for row in dim2s:
    print('\t', row)
print("]", '\n')

print("Sorted by lastname then firstname: ")
dim2s = sorted(dim2, key=by_2dim_lastname_firstname)      #sort 2 dim by lastname then firstname
print("[", end="")
for row in dim2s:
    print('\t', row)
print("]", '\n')

print("Sorted by lname & fname (using lambda function): ")  #sort 2 dim using a lamdba function
dim2s = sorted(dim2, key=lambda elem: (elem[1],elem[0]) )   #a lambda function          
print("[", end="")
for row in dim2s:                                           #takes an element (a list)
    print('\t', row)                                        #returns elem1 and elem0 
print("]", '\n')


print("\n-------------- Dictionary -----------------------------------------------------------------")

dict  = {'fname':'Sam', 'lname':'Sultan', 'middle':'E', 'sex':'male', 'age':'unknown'}
print("The original dictionary: ", dict) 
print() 
for key in dict:
    print('\t' , key, '=>', dict[key])  
print()

print("Sorted by keys: ")                                #sort by keys
keys = dict.keys()                                       #get the keys as a list
keys = sorted(keys)                                      #sort the keys
for key in keys:
    print('\t' , key, '=>', dict[key])  
print()

print("Sorted by keys, Another way: ")                   #sort by keys (another way)
listOfTuples = sorted(dict.items())                      #dict.items() = list of tuples         
for (key, value) in listOfTuples :                       #sort the list of tuples                                  
    print('\t' , key, '=>', value)                           
print()

print("Sorted by values: ")                              #sort by values
listOfTuples = sorted(dict.items(), key=by_value) 
for (key, value) in listOfTuples :
    print('\t' , key, '=>', value)  
print()

print("Sorted by values (using lambda function): ")                 #sort by values using a lamdba function
listOfTuples = sorted(dict.items(), key=lambda elem: elem[1] )      #a lambda function  
for (key, value) in listOfTuples :                                  #takes an element (a name/value tuple)
    print('\t' , key, '=>', value)                                  #returns the value component
print()

print("Sorted by values descending, case insensitive (using lambda function): ")
listOfTuples = sorted(dict.items(), key=lambda elem: elem[1].lower(), reverse=True ) 
for (key, value) in listOfTuples :
    print('\t' , key, '=>', value)  
print()